@@ -18,6 +18,7 @@ package dbtest
18
18
19
19
import (
20
20
"bytes"
21
+ "math/rand"
21
22
"reflect"
22
23
"sort"
23
24
"testing"
@@ -377,6 +378,101 @@ func TestDatabaseSuite(t *testing.T, New func() ethdb.KeyValueStore) {
377
378
})
378
379
}
379
380
381
+ // BenchDatabaseSuite runs a suite of benchmarks against a KeyValueStore database
382
+ // implementation.
383
+ func BenchDatabaseSuite (b * testing.B , New func () ethdb.KeyValueStore ) {
384
+ var (
385
+ keys , vals = makeDataset (1_000_000 , 32 , 32 , false )
386
+ sKeys , sVals = makeDataset (1_000_000 , 32 , 32 , true )
387
+ )
388
+ // Run benchmarks sequentially
389
+ b .Run ("Write" , func (b * testing.B ) {
390
+ benchWrite := func (b * testing.B , keys , vals [][]byte ) {
391
+ b .ResetTimer ()
392
+ b .ReportAllocs ()
393
+
394
+ db := New ()
395
+ defer db .Close ()
396
+
397
+ for i := 0 ; i < len (keys ); i ++ {
398
+ db .Put (keys [i ], vals [i ])
399
+ }
400
+ }
401
+ b .Run ("WriteSorted" , func (b * testing.B ) {
402
+ benchWrite (b , sKeys , sVals )
403
+ })
404
+ b .Run ("WriteRandom" , func (b * testing.B ) {
405
+ benchWrite (b , keys , vals )
406
+ })
407
+ })
408
+ b .Run ("Read" , func (b * testing.B ) {
409
+ benchRead := func (b * testing.B , keys , vals [][]byte ) {
410
+ db := New ()
411
+ defer db .Close ()
412
+
413
+ for i := 0 ; i < len (keys ); i ++ {
414
+ db .Put (keys [i ], vals [i ])
415
+ }
416
+ b .ResetTimer ()
417
+ b .ReportAllocs ()
418
+
419
+ for i := 0 ; i < len (keys ); i ++ {
420
+ db .Get (keys [i ])
421
+ }
422
+ }
423
+ b .Run ("ReadSorted" , func (b * testing.B ) {
424
+ benchRead (b , sKeys , sVals )
425
+ })
426
+ b .Run ("ReadRandom" , func (b * testing.B ) {
427
+ benchRead (b , keys , vals )
428
+ })
429
+ })
430
+ b .Run ("Iteration" , func (b * testing.B ) {
431
+ benchIteration := func (b * testing.B , keys , vals [][]byte ) {
432
+ db := New ()
433
+ defer db .Close ()
434
+
435
+ for i := 0 ; i < len (keys ); i ++ {
436
+ db .Put (keys [i ], vals [i ])
437
+ }
438
+ b .ResetTimer ()
439
+ b .ReportAllocs ()
440
+
441
+ it := db .NewIterator (nil , nil )
442
+ for it .Next () {
443
+ }
444
+ it .Release ()
445
+ }
446
+ b .Run ("IterationSorted" , func (b * testing.B ) {
447
+ benchIteration (b , sKeys , sVals )
448
+ })
449
+ b .Run ("IterationRandom" , func (b * testing.B ) {
450
+ benchIteration (b , keys , vals )
451
+ })
452
+ })
453
+ b .Run ("BatchWrite" , func (b * testing.B ) {
454
+ benchBatchWrite := func (b * testing.B , keys , vals [][]byte ) {
455
+ b .ResetTimer ()
456
+ b .ReportAllocs ()
457
+
458
+ db := New ()
459
+ defer db .Close ()
460
+
461
+ batch := db .NewBatch ()
462
+ for i := 0 ; i < len (keys ); i ++ {
463
+ batch .Put (keys [i ], vals [i ])
464
+ }
465
+ batch .Write ()
466
+ }
467
+ b .Run ("BenchWriteSorted" , func (b * testing.B ) {
468
+ benchBatchWrite (b , sKeys , sVals )
469
+ })
470
+ b .Run ("BenchWriteRandom" , func (b * testing.B ) {
471
+ benchBatchWrite (b , keys , vals )
472
+ })
473
+ })
474
+ }
475
+
380
476
func iterateKeys (it ethdb.Iterator ) []string {
381
477
keys := []string {}
382
478
for it .Next () {
@@ -386,3 +482,25 @@ func iterateKeys(it ethdb.Iterator) []string {
386
482
it .Release ()
387
483
return keys
388
484
}
485
+
486
+ // randomHash generates a random blob of data and returns it as a hash.
487
+ func randBytes (len int ) []byte {
488
+ buf := make ([]byte , len )
489
+ if n , err := rand .Read (buf ); n != len || err != nil {
490
+ panic (err )
491
+ }
492
+ return buf
493
+ }
494
+
495
+ func makeDataset (size , ksize , vsize int , order bool ) ([][]byte , [][]byte ) {
496
+ var keys [][]byte
497
+ var vals [][]byte
498
+ for i := 0 ; i < size ; i += 1 {
499
+ keys = append (keys , randBytes (ksize ))
500
+ vals = append (vals , randBytes (vsize ))
501
+ }
502
+ if order {
503
+ sort .Slice (keys , func (i , j int ) bool { return bytes .Compare (keys [i ], keys [j ]) < 0 })
504
+ }
505
+ return keys , vals
506
+ }
0 commit comments