diff --git a/store/README.md b/store/README.md new file mode 100644 index 0000000000000000000000000000000000000000..d388fa6046d23c03cc5eb2ab4dc941c0ebed15a8 --- /dev/null +++ b/store/README.md @@ -0,0 +1,35 @@ +Results of benchmarking +------------------------ + +Using RocksDB + +So, reading times are on the order of single unit microseconds, while writing +times with `Sync` set to true are ~30 milliseconds. + +``` +$ go test -run BenchmarkSet -v -bench . +PASS +BenchmarkGet_valsize100-6 500000 2850 ns/op +--- BENCH: BenchmarkGet_valsize100-6 + store_test.go:85: Wrote 100 keys. + store_test.go:85: Wrote 100 keys. + store_test.go:85: Wrote 100 keys. + store_test.go:85: Wrote 100 keys. +BenchmarkGet_valsize1000-6 500000 3565 ns/op +--- BENCH: BenchmarkGet_valsize1000-6 + store_test.go:85: Wrote 100 keys. + store_test.go:85: Wrote 100 keys. + store_test.go:85: Wrote 100 keys. + store_test.go:85: Wrote 100 keys. +BenchmarkGet_valsize10000-6 200000 8541 ns/op +--- BENCH: BenchmarkGet_valsize10000-6 + store_test.go:85: Wrote 100 keys. + store_test.go:85: Wrote 100 keys. + store_test.go:85: Wrote 100 keys. + store_test.go:85: Wrote 100 keys. + store_test.go:85: Wrote 100 keys. +BenchmarkSet_valsize100-6 50 32932578 ns/op +BenchmarkSet_valsize1000-6 50 28066678 ns/op +BenchmarkSet_valsize10000-6 50 28736228 ns/op +ok github.com/dgraph-io/dgraph/store 48.393s +``` diff --git a/store/store.go b/store/store.go index e29abdeefa097252a6f569ee0334459876a171c7..37b197b4ff61d7edaf4f8ec01c8b60c16611b4f1 100644 --- a/store/store.go +++ b/store/store.go @@ -17,21 +17,29 @@ package store import ( + "github.com/dgraph-io/dgraph/store/rocksdb" "github.com/dgraph-io/dgraph/x" - "github.com/syndtr/goleveldb/leveldb" - "github.com/syndtr/goleveldb/leveldb/opt" ) var log = x.Log("store") type Store struct { - db *leveldb.DB - opt *opt.Options + db *rocksdb.DB + opt *rocksdb.Options + ropt *rocksdb.ReadOptions + wopt *rocksdb.WriteOptions } func (s *Store) Init(filepath string) { + s.opt = rocksdb.NewOptions() + s.opt.SetCreateIfMissing(true) + + s.ropt = rocksdb.NewReadOptions() + s.wopt = rocksdb.NewWriteOptions() + s.wopt.SetSync(true) + var err error - s.db, err = leveldb.OpenFile(filepath, s.opt) + s.db, err = rocksdb.Open(filepath, s.opt) if err != nil { x.Err(log, err).WithField("filepath", filepath). Fatal("While opening store") @@ -39,24 +47,24 @@ func (s *Store) Init(filepath string) { } } +/* func (s *Store) IsNew(id uint64) bool { return false } +*/ -func (s *Store) Get(k []byte) (val []byte, rerr error) { - return s.db.Get(k, nil) +func (s *Store) Get(key []byte) (val []byte, rerr error) { + return s.db.Get(s.ropt, key) } func (s *Store) SetOne(k []byte, val []byte) error { - wb := new(leveldb.Batch) - wb.Put(k, val) - return s.db.Write(wb, nil) + return s.db.Put(s.wopt, k, val) } func (s *Store) Delete(k []byte) error { - return s.db.Delete(k, nil) + return s.db.Delete(s.wopt, k) } -func (s *Store) Close() error { - return s.db.Close() +func (s *Store) Close() { + s.db.Close() } diff --git a/store/store_test.go b/store/store_test.go index a8860d527059c87ee9955861269653233a072c31..0f98232398240eb9aa01aacacb7767c903fc0d57 100644 --- a/store/store_test.go +++ b/store/store_test.go @@ -17,7 +17,9 @@ package store import ( + "fmt" "io/ioutil" + "math/rand" "os" "testing" ) @@ -58,3 +60,71 @@ func TestGet(t *testing.T) { t.Errorf("Expected 'the one'. Found: %s", string(val)) } } + +func benchmarkGet(valSize int, b *testing.B) { + path, err := ioutil.TempDir("", "storetest_") + if err != nil { + b.Error(err) + b.Fail() + return + } + defer os.RemoveAll(path) + + var s Store + s.Init(path) + buf := make([]byte, valSize) + + nkeys := 100 + for i := 0; i < nkeys; i++ { + key := []byte(fmt.Sprintf("key_%d", i)) + if err := s.SetOne(key, buf); err != nil { + b.Error(err) + return + } + } + b.Logf("Wrote %d keys.", nkeys) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + k := rand.Int() % nkeys + key := []byte(fmt.Sprintf("key_%d", k)) + val, err := s.Get(key) + if err != nil { + b.Error(err) + } + if len(val) != valSize { + b.Errorf("Value size expected: %d. Found: %d", valSize, len(val)) + } + } +} + +func BenchmarkGet_valsize100(b *testing.B) { benchmarkGet(100, b) } +func BenchmarkGet_valsize1000(b *testing.B) { benchmarkGet(1000, b) } +func BenchmarkGet_valsize10000(b *testing.B) { benchmarkGet(10000, b) } + +func benchmarkSet(valSize int, b *testing.B) { + path, err := ioutil.TempDir("", "storetest_") + if err != nil { + b.Error(err) + b.Fail() + return + } + defer os.RemoveAll(path) + + var s Store + s.Init(path) + buf := make([]byte, valSize) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + key := []byte(fmt.Sprintf("key_%d", i)) + if err := s.SetOne(key, buf); err != nil { + b.Error(err) + return + } + } +} + +func BenchmarkSet_valsize100(b *testing.B) { benchmarkSet(100, b) } +func BenchmarkSet_valsize1000(b *testing.B) { benchmarkSet(1000, b) } +func BenchmarkSet_valsize10000(b *testing.B) { benchmarkSet(10000, b) }