From 083b82a0f1bfd28f9b8ad6071825a367f11552c2 Mon Sep 17 00:00:00 2001 From: yosssi Date: Wed, 18 Jun 2014 14:16:41 +0900 Subject: [PATCH] Add benchmarks --- store/store_test.go | 292 +++++++++++++++++++++++++++++++++++++++----- wercker.yml | 3 +- 2 files changed, 260 insertions(+), 35 deletions(-) diff --git a/store/store_test.go b/store/store_test.go index c04b9ce..70603b2 100644 --- a/store/store_test.go +++ b/store/store_test.go @@ -1,26 +1,81 @@ package store import ( + "fmt" "net/http" "net/http/httptest" + "strconv" "testing" "time" + "code.google.com/p/gogoprotobuf/proto" "github.com/boltdb/bolt" "github.com/gorilla/securecookie" "github.com/gorilla/sessions" + "github.com/yosssi/boltstore/shared" ) +var benchmarkDB = fmt.Sprintf("benchmark_store_%d.db", time.Now().Unix()) + +func init() { + // Put data to the database for the benchmark. + db, err := bolt.Open(benchmarkDB, 0666) + if err != nil { + panic(err) + } + defer db.Close() + + err = db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte(shared.DefaultBucketName)) + if err != nil { + return err + } + return nil + }) + if err != nil { + panic(err) + } + data, err := proto.Marshal(shared.NewSession([]byte{}, shared.DefaultMaxAge)) + if err != nil { + panic(err) + } + + fmt.Printf("Start putting data for the benchmark %+v\n", time.Now()) + + for i := 0; i < 100; i++ { + err = db.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte(shared.DefaultBucketName)) + for j := 0; j < 100000; j++ { + if err := bucket.Put([]byte(strconv.Itoa(100000*i+j)), data); err != nil { + return err + } + } + return nil + }) + if err != nil { + panic(err) + } + if (i+1)%10 == 0 { + fmt.Printf("%d key-values were put.\n", (i+1)*100000) + } + } + + fmt.Printf("End putting data for the benchmark %+v\n", time.Now()) + if err != nil { + panic(err) + } +} + func TestStore_Get(t *testing.T) { db, err := bolt.Open("./sessions.db", 0666) if err != nil { - t.Error(err.Error()) + t.Error(err) } defer db.Close() req, err := http.NewRequest("GET", "http://localhost:3000/", nil) if err != nil { - t.Error(err.Error()) + t.Error(err) } str, err := New( @@ -29,12 +84,12 @@ func TestStore_Get(t *testing.T) { []byte("secret-key"), ) if err != nil { - t.Error(err.Error()) + t.Error(err) } session, err := str.Get(req, "test") if err != nil { - t.Error(err.Error()) + t.Error(err) } if session.IsNew != true { @@ -45,7 +100,7 @@ func TestStore_Get(t *testing.T) { func TestStore_New(t *testing.T) { db, err := bolt.Open("./sessions.db", 0666) if err != nil { - t.Error(err.Error()) + t.Error(err) } defer db.Close() @@ -55,12 +110,12 @@ func TestStore_New(t *testing.T) { []byte("secret-key"), ) if err != nil { - t.Error(err.Error()) + t.Error(err) } req, err := http.NewRequest("GET", "http://localhost:3000/", nil) if err != nil { - t.Error(err.Error()) + t.Error(err) } encoded, err := securecookie.EncodeMulti("test", "1", str.codecs...) @@ -71,7 +126,7 @@ func TestStore_New(t *testing.T) { session, err := str.New(req, "test") if err != nil { - t.Error(err.Error()) + t.Error(err) } if session.IsNew != true { @@ -83,7 +138,7 @@ func TestStore_Save(t *testing.T) { // When session.Options.MaxAge < 0 db, err := bolt.Open("./sessions.db", 0666) if err != nil { - t.Error(err.Error()) + t.Error(err) } defer db.Close() @@ -93,54 +148,62 @@ func TestStore_Save(t *testing.T) { []byte("secret-key"), ) if err != nil { - t.Error(err.Error()) + t.Error(err) } req, err := http.NewRequest("GET", "http://localhost:3000/", nil) if err != nil { - t.Error(err.Error()) + t.Error(err) } session, err := str.Get(req, "test") if err != nil { - t.Error(err.Error()) + t.Error(err) } session.Options.MaxAge = -1 w := httptest.NewRecorder() - str.Save(req, w, session) + if err := str.Save(req, w, session); err != nil { + t.Error(err) + } // When session.Options.MaxAge >= 0 session, err = str.Get(req, "test") if err != nil { - t.Error(err.Error()) + t.Error(err) } session.Options.MaxAge = 1 w = httptest.NewRecorder() - str.Save(req, w, session) + if err := str.Save(req, w, session); err != nil { + t.Error(err) + } // When session.Options.MaxAge >= 0 and // s.save returns an error session.Values = make(map[interface{}]interface{}) session.Values[make(chan int)] = make(chan int) - str.Save(req, w, session) + if err := str.Save(req, w, session); err == nil || err.Error() != "gob: type not registered for interface: chan int" { + t.Error(`str.Save should return an error "%s" (actual: %+v)`, "gob: type not registered for interface: chan int", err) + } // When session.Options.MaxAge >= 0 and // securecookie.EncodeMulti returns an error session.Values = make(map[interface{}]interface{}) str.codecs = nil - str.Save(req, w, session) + if err := str.Save(req, w, session); err == nil || err.Error() != "securecookie: no codecs provided" { + t.Error(`str.Save should return an error "%s" (actual: %+v)`, "securecookie: no codecs provided", err) + } } func TestStore_load(t *testing.T) { db, err := bolt.Open("./sessions.db", 0666) if err != nil { - t.Error(err.Error()) + t.Error(err) } defer db.Close() @@ -150,26 +213,28 @@ func TestStore_load(t *testing.T) { []byte("secret-key"), ) if err != nil { - t.Error(err.Error()) + t.Error(err) } req, err := http.NewRequest("GET", "http://localhost:3000/", nil) if err != nil { - t.Error(err.Error()) + t.Error(err) } session, err := str.Get(req, "test") if err != nil { - t.Error(err.Error()) + t.Error(err) } w := httptest.NewRecorder() - str.Save(req, w, session) + if err := str.Save(req, w, session); err != nil { + t.Error(err) + } exists, err := str.load(session) if err != nil { - t.Error(err.Error()) + t.Error(err) } if exists != true { @@ -180,7 +245,7 @@ func TestStore_load(t *testing.T) { session.ID = "x" exists, err = str.load(session) if err != nil { - t.Error(err.Error()) + t.Error(err) } if exists != false { @@ -192,7 +257,7 @@ func TestStore_load(t *testing.T) { return tx.Bucket(str.config.DBOptions.BucketName).Put([]byte("x"), []byte("test")) }) if err != nil { - t.Error(err.Error()) + t.Error(err) } _, err = str.load(session) if err == nil || err.Error() != "proto: field/encoding mismatch: wrong type for field" { @@ -202,21 +267,24 @@ func TestStore_load(t *testing.T) { // When the target session data is expired session, err = str.Get(req, "test") if err != nil { - t.Error(err.Error()) + t.Error(err) } session.Options.MaxAge = 0 - str.Save(req, w, session) + if err := str.Save(req, w, session); err != nil { + t.Error(err) + } + time.Sleep(time.Second) _, err = str.load(session) if err != nil { - t.Error(err.Error()) + t.Error(err) } } func TestSession_delete(t *testing.T) { db, err := bolt.Open("./sessions.db", 0666) if err != nil { - t.Error(err.Error()) + t.Error(err) } defer db.Close() @@ -226,17 +294,17 @@ func TestSession_delete(t *testing.T) { []byte("secret-key"), ) if err != nil { - t.Error(err.Error()) + t.Error(err) } req, err := http.NewRequest("GET", "http://localhost:3000/", nil) if err != nil { - t.Error(err.Error()) + t.Error(err) } session, err := str.Get(req, "test") if err != nil { - t.Error(err.Error()) + t.Error(err) } db.Close() @@ -252,7 +320,7 @@ func TestNew(t *testing.T) { // When db.Update returns an error db, err := bolt.Open("./sessions.db", 0666) if err != nil { - t.Error(err.Error()) + t.Error(err) } db.Close() @@ -372,3 +440,161 @@ func ExampleNew() { // Add a value on the session. session.Values["foo"] = "bar" } + +func BenchmarkNew(b *testing.B) { + db, err := bolt.Open(benchmarkDB, 0666) + if err != nil { + b.Error(err) + } + + defer db.Close() + + for i := 0; i < b.N; i++ { + _, err = New( + db, + Config{}, + []byte("secret-key"), + ) + if err != nil { + b.Error(err) + } + } +} + +func BenchmarkStore_Get(b *testing.B) { + db, err := bolt.Open(benchmarkDB, 0666) + if err != nil { + b.Error(err) + } + + defer db.Close() + + str, err := New( + db, + Config{}, + []byte("secret-key"), + ) + if err != nil { + b.Error(err) + } + + req, err := http.NewRequest("GET", "http://localhost:3000/", nil) + if err != nil { + b.Error(err) + } + + for i := 0; i < b.N; i++ { + _, err := str.Get(req, "test") + if err != nil { + b.Error(err) + } + } +} + +func BenchmarkStore_New(b *testing.B) { + db, err := bolt.Open(benchmarkDB, 0666) + if err != nil { + b.Error(err) + } + + defer db.Close() + + str, err := New( + db, + Config{}, + []byte("secret-key"), + ) + if err != nil { + b.Error(err) + } + + req, err := http.NewRequest("GET", "http://localhost:3000/", nil) + if err != nil { + b.Error(err) + } + + for i := 0; i < b.N; i++ { + _, err := str.New(req, "test") + if err != nil { + b.Error(err) + } + } +} + +func BenchmarkStore_Save(b *testing.B) { + db, err := bolt.Open(benchmarkDB, 0666) + if err != nil { + b.Error(err) + } + + defer db.Close() + + str, err := New( + db, + Config{}, + []byte("secret-key"), + ) + if err != nil { + b.Error(err) + } + + req, err := http.NewRequest("GET", "http://localhost:3000/", nil) + if err != nil { + b.Error(err) + } + + w := httptest.NewRecorder() + + session, err := str.Get(req, "test") + if err != nil { + b.Error(err) + } + + session.Values["foo"] = "bar" + + for i := 0; i < b.N; i++ { + if err := str.Save(req, w, session); err != nil { + b.Error(err) + } + } +} + +func BenchmarkStore_Save_delete(b *testing.B) { + db, err := bolt.Open(benchmarkDB, 0666) + if err != nil { + b.Error(err) + } + + defer db.Close() + + str, err := New( + db, + Config{}, + []byte("secret-key"), + ) + if err != nil { + b.Error(err) + } + + req, err := http.NewRequest("GET", "http://localhost:3000/", nil) + if err != nil { + b.Error(err) + } + + w := httptest.NewRecorder() + + session, err := str.Get(req, "test") + if err != nil { + b.Error(err) + } + + session.Values["foo"] = "bar" + + session.Options.MaxAge = -1 + + for i := 0; i < b.N; i++ { + if err := str.Save(req, w, session); err != nil { + b.Error(err) + } + } +} diff --git a/wercker.yml b/wercker.yml index 8f3ff3c..0cf9e4b 100644 --- a/wercker.yml +++ b/wercker.yml @@ -25,8 +25,7 @@ build: - script: name: go test code: | - go test --cover ./... - + go test -bench . -benchmem -cover ./... # Invoke goveralls - script: name: goveralls