mirror of
https://github.com/taigrr/bitcask
synced 2025-01-18 04:03:17 -08:00
Adds WithSync(...) option to turn on sync after write durability (#63)
* Added WithSync(...) option to turn on sync after write durability * Add Sync/NoSync benchmark variants for Put()
This commit is contained in:
parent
8f56cffd86
commit
c5a565cd82
@ -155,6 +155,12 @@ func (b *Bitcask) Put(key, value []byte) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if b.config.sync {
|
||||||
|
if err := b.curr.Sync(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
item := b.keydir.Add(key, b.curr.FileID(), offset, n)
|
item := b.keydir.Add(key, b.curr.FileID(), offset, n)
|
||||||
b.trie.Add(string(key), item)
|
b.trie.Add(string(key), item)
|
||||||
|
|
||||||
|
@ -566,18 +566,6 @@ func BenchmarkPut(b *testing.B) {
|
|||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
testdir, err := ioutil.TempDir(currentDir, "bitcask_bench")
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(testdir)
|
|
||||||
|
|
||||||
db, err := Open(testdir)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
tests := []benchmarkTestCase{
|
tests := []benchmarkTestCase{
|
||||||
{"128B", 128},
|
{"128B", 128},
|
||||||
{"256B", 256},
|
{"256B", 256},
|
||||||
@ -589,20 +577,43 @@ func BenchmarkPut(b *testing.B) {
|
|||||||
{"32K", 32768},
|
{"32K", 32768},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
variants := map[string][]Option{
|
||||||
b.Run(tt.name, func(b *testing.B) {
|
"NoSync": []Option{
|
||||||
b.SetBytes(int64(tt.size))
|
WithSync(false),
|
||||||
|
},
|
||||||
|
"Sync": []Option{
|
||||||
|
WithSync(true),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
key := []byte("foo")
|
for name, options := range variants {
|
||||||
value := []byte(strings.Repeat(" ", tt.size))
|
testdir, err := ioutil.TempDir(currentDir, "bitcask_bench")
|
||||||
b.ResetTimer()
|
if err != nil {
|
||||||
for i := 0; i < b.N; i++ {
|
b.Fatal(err)
|
||||||
err := db.Put(key, value)
|
}
|
||||||
if err != nil {
|
defer os.RemoveAll(testdir)
|
||||||
b.Fatal(err)
|
|
||||||
|
db, err := Open(testdir, options...)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
b.Run(tt.name+name, func(b *testing.B) {
|
||||||
|
b.SetBytes(int64(tt.size))
|
||||||
|
|
||||||
|
key := []byte("foo")
|
||||||
|
value := []byte(strings.Repeat(" ", tt.size))
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
err := db.Put(key, value)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
26
options.go
26
options.go
@ -24,25 +24,29 @@ type config struct {
|
|||||||
maxDatafileSize int
|
maxDatafileSize int
|
||||||
maxKeySize int
|
maxKeySize int
|
||||||
maxValueSize int
|
maxValueSize int
|
||||||
|
sync bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *config) MarshalJSON() ([]byte, error) {
|
func (c *config) MarshalJSON() ([]byte, error) {
|
||||||
return json.Marshal(struct {
|
return json.Marshal(struct {
|
||||||
MaxDatafileSize int `json:"max_datafile_size"`
|
MaxDatafileSize int `json:"max_datafile_size"`
|
||||||
MaxKeySize int `json:"max_key_size"`
|
MaxKeySize int `json:"max_key_size"`
|
||||||
MaxValueSize int `json:"max_value_size"`
|
MaxValueSize int `json:"max_value_size"`
|
||||||
|
Sync bool `json:"sync"`
|
||||||
}{
|
}{
|
||||||
MaxDatafileSize: c.maxDatafileSize,
|
MaxDatafileSize: c.maxDatafileSize,
|
||||||
MaxKeySize: c.maxKeySize,
|
MaxKeySize: c.maxKeySize,
|
||||||
MaxValueSize: c.maxValueSize,
|
MaxValueSize: c.maxValueSize,
|
||||||
|
Sync: c.sync,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func getConfig(path string) (*config, error) {
|
func getConfig(path string) (*config, error) {
|
||||||
type Config struct {
|
type Config struct {
|
||||||
MaxDatafileSize int `json:"max_datafile_size"`
|
MaxDatafileSize int `json:"max_datafile_size"`
|
||||||
MaxKeySize int `json:"max_key_size"`
|
MaxKeySize int `json:"max_key_size"`
|
||||||
MaxValueSize int `json:"max_value_size"`
|
MaxValueSize int `json:"max_value_size"`
|
||||||
|
Sync bool `json:"sync"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var cfg Config
|
var cfg Config
|
||||||
@ -60,6 +64,7 @@ func getConfig(path string) (*config, error) {
|
|||||||
maxDatafileSize: cfg.MaxDatafileSize,
|
maxDatafileSize: cfg.MaxDatafileSize,
|
||||||
maxKeySize: cfg.MaxKeySize,
|
maxKeySize: cfg.MaxKeySize,
|
||||||
maxValueSize: cfg.MaxValueSize,
|
maxValueSize: cfg.MaxValueSize,
|
||||||
|
sync: cfg.Sync,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,3 +99,12 @@ func WithMaxValueSize(size int) Option {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithSync causes Sync() to be called on every key/value written increasing
|
||||||
|
// durability and saftey at the expense of performance
|
||||||
|
func WithSync(sync bool) Option {
|
||||||
|
return func(cfg *config) error {
|
||||||
|
cfg.sync = sync
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user