Browse Source

Add delete and benchmarks

Signed-off-by: jolheiser <john.olheiser@gmail.com>
main
jolheiser 5 months ago
parent
commit
23d22dbce1
Signed by: jolheiser GPG Key ID: B853ADA5DA7BBF7A
  1. 18
      .drone.yml
  2. 6
      Makefile
  3. 8
      bench.txt
  4. 5
      bucket.go
  5. 2
      go.mod
  6. 2
      serial.go
  7. 62
      serial_test.go
  8. 28
      store.go
  9. 44
      store_test.go

18
.drone.yml

@ -0,0 +1,18 @@
---
kind: pipeline
name: compliance
trigger:
event:
- pull_request
steps:
- name: test
pull: always
image: golang:1.16
commands:
- make test
- name: check
pull: always
image: golang:1.16
commands:
- make vet
- diff <(gofmt -d .) <(echo -n)

6
Makefile

@ -6,12 +6,16 @@ fmt:
.PHONY: test
test:
$(GO) test --race ./...
$(GO) test -v --race ./...
.PHONY: vet
vet:
$(GO) vet ./...
.PHONY: bench
bench:
$(GO) test -benchmem -bench=. > bench.txt
.PHONY: coverage
coverage:
$(GO) test --coverprofile=coverage.out

8
bench.txt

@ -0,0 +1,8 @@
goos: linux
goarch: amd64
pkg: go.jolheiser.com/shock
cpu: Intel(R) Core(TM) i7-4700MQ CPU @ 2.40GHz
BenchmarkJSON-8 56 22729619 ns/op 40494 B/op 305 allocs/op
BenchmarkGob-8 56 23260793 ns/op 65582 B/op 933 allocs/op
PASS
ok go.jolheiser.com/shock 2.754s

5
bucket.go

@ -21,6 +21,11 @@ func (b *Bucket) Get(id, val interface{}) error {
return b.DB.Get(b.Name, id, val)
}
// Delete removes a value from the bucket with the specified sequence ID
func (b *Bucket) Delete(id interface{}) error {
return b.DB.Delete(b.Name, id)
}
// Count returns the number of objects in the bucket
func (b *Bucket) Count() (int, error) {
return b.DB.Count(b.Name)

2
go.mod

@ -1,5 +1,5 @@
module go.jolheiser.com/shock
go 1.14
go 1.16
require go.etcd.io/bbolt v1.3.5

2
serial.go

@ -22,7 +22,7 @@ func (j JSONSerializer) Marshal(v interface{}) ([]byte, error) {
// Unmarshal decodes an object from JSON
func (j JSONSerializer) Unmarshal(data []byte, v interface{}) error {
return json.Unmarshal(data, &v)
return json.Unmarshal(data, v)
}
// GobSerializer is a Serializer that uses gob

62
serial_test.go

@ -25,7 +25,67 @@ func TestGob(t *testing.T) {
t.FailNow()
}
testStore(t, bucket)
testCases(t, bucket, true)
if err := gobDB.Bolt.Close(); err != nil {
fmt.Printf("Could not close DB %s: %v\n", dbPath, err)
}
}
func BenchmarkJSON(b *testing.B) {
b.StopTimer()
dbPath := path.Join(tmpDir, "json.db")
jsonDB, err := Open(dbPath, os.ModePerm, &Options{
Bolt: bbolt.DefaultOptions,
Serializer: JSONSerializer{},
})
if err != nil {
panic(err)
}
bucket := jsonDB.Bucket("json")
if err := bucket.Init(); err != nil {
b.Log(err)
b.FailNow()
}
b.StartTimer()
for idx := 0; idx < b.N; idx++ {
for _, tc := range tt {
testStore(b, tc, bucket, true)
}
}
b.StopTimer()
if err := jsonDB.Bolt.Close(); err != nil {
fmt.Printf("Could not close DB %s: %v\n", dbPath, err)
}
}
func BenchmarkGob(b *testing.B) {
b.StopTimer()
dbPath := path.Join(tmpDir, "gob.db")
gobDB, err := Open(dbPath, os.ModePerm, &Options{
Bolt: bbolt.DefaultOptions,
Serializer: GobSerializer{},
})
if err != nil {
panic(err)
}
bucket := gobDB.Bucket("gob")
if err := bucket.Init(); err != nil {
b.Log(err)
b.FailNow()
}
b.StartTimer()
for idx := 0; idx < b.N; idx++ {
for _, tc := range tt {
testStore(b, tc, bucket, true)
}
}
b.StopTimer()
if err := gobDB.Bolt.Close(); err != nil {
fmt.Printf("Could not close DB %s: %v\n", dbPath, err)

28
store.go

@ -39,33 +39,37 @@ func (d *DB) PutWithKey(bucket string, key, val interface{}) error {
if err != nil {
return err
}
return b.Put([]byte(fmt.Sprintf("%v", key)), serial)
return b.Put([]byte(fmt.Sprint(key)), serial)
})
}
// Get returns a value from a bucket with the specified sequence ID
func (d *DB) Get(bucket string, id, val interface{}) error {
if err := d.Bolt.View(func(tx *bbolt.Tx) error {
serial := tx.Bucket([]byte(bucket)).Get([]byte(fmt.Sprintf("%v", id)))
err := d.Bolt.View(func(tx *bbolt.Tx) error {
serial := tx.Bucket([]byte(bucket)).Get([]byte(fmt.Sprint(id)))
return d.Serializer.Unmarshal(serial, val)
}); err != nil {
return err
}
return nil
})
return err
}
// Delete removes a value from the bucket with the specified sequence ID
func (d *DB) Delete(bucket string, id interface{}) error {
err := d.Bolt.Update(func(tx *bbolt.Tx) error {
return tx.Bucket([]byte(bucket)).Delete([]byte(fmt.Sprint(id)))
})
return err
}
// Count returns the number of objects in a bucket
func (d *DB) Count(bucket string) (int, error) {
count := 0
if err := d.Bolt.View(func(tx *bbolt.Tx) error {
err := d.Bolt.View(func(tx *bbolt.Tx) error {
return tx.Bucket([]byte(bucket)).ForEach(func(_, _ []byte) error {
count++
return nil
})
}); err != nil {
return count, err
}
return count, nil
})
return count, err
}
// EachFunc defines a way to interact with each object in a bucket while iterating

44
store_test.go

@ -41,7 +41,7 @@ func TestStore(t *testing.T) {
t.FailNow()
}
testStore(t, bucket)
testCases(t, bucket, false)
t.Run("count", func(t *testing.T) {
count, err := bucket.Count()
@ -100,26 +100,36 @@ func TestStore(t *testing.T) {
}
}
func testStore(t *testing.T, bucket *Bucket) {
func testCases(t *testing.T, bucket *Bucket, delete bool) {
for _, tc := range tt {
t.Run(tc.Name, func(t *testing.T) {
if err := bucket.Put(tc); err != nil {
t.Log(err)
t.FailNow()
}
testStore(t, tc, bucket, delete)
})
}
}
var tcc TestUser
err := bucket.Get(tc.ID, &tcc)
if err != nil {
t.Log(err)
t.FailNow()
}
func testStore(t testing.TB, tc *TestUser, bucket *Bucket, delete bool) {
if err := bucket.Put(tc); err != nil {
t.Log(err)
t.FailNow()
}
if !tcc.Equal(*tc) {
t.Log("Serialized struct is not the same")
t.FailNow()
}
})
var tcc TestUser
if err := bucket.Get(tc.ID, &tcc); err != nil {
t.Log(err)
t.FailNow()
}
if !tcc.Equal(*tc) {
t.Log("Serialized struct is not the same")
t.FailNow()
}
if delete {
if err := bucket.Delete(tc.ID); err != nil {
t.Log(err)
t.FailNow()
}
}
}

Loading…
Cancel
Save