@@ -18,6 +18,7 @@ package dbtest
1818
1919import (
2020 "bytes"
21+ "math/rand"
2122 "reflect"
2223 "sort"
2324 "testing"
@@ -377,6 +378,101 @@ func TestDatabaseSuite(t *testing.T, New func() ethdb.KeyValueStore) {
377378 })
378379}
379380
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+
380476func iterateKeys (it ethdb.Iterator ) []string {
381477 keys := []string {}
382478 for it .Next () {
@@ -386,3 +482,25 @@ func iterateKeys(it ethdb.Iterator) []string {
386482 it .Release ()
387483 return keys
388484}
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