first commit
This commit is contained in:
parent
7656005724
commit
53fb3f0569
7 changed files with 497 additions and 0 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -20,3 +20,4 @@ _cgo_export.*
|
||||||
_testmain.go
|
_testmain.go
|
||||||
|
|
||||||
*.exe
|
*.exe
|
||||||
|
.DS_Store
|
||||||
|
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "src"]
|
||||||
|
path = src
|
||||||
|
url = https://github.com/unqlite/unqlite.git
|
5
Makefile
Normal file
5
Makefile
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# for GNU make
|
||||||
|
|
||||||
|
libunqlite.a: src/unqlite.c src/unqlite.h
|
||||||
|
gcc -c src/unqlite.c -I./src -DUNQLITE_ENABLE_THREADS=1
|
||||||
|
ar rv libunqlite.a unqlite.o
|
22
README.md
22
README.md
|
@ -2,3 +2,25 @@ unqlitego
|
||||||
=========
|
=========
|
||||||
|
|
||||||
UnQLite Binding for golang.
|
UnQLite Binding for golang.
|
||||||
|
|
||||||
|
Install
|
||||||
|
---------
|
||||||
|
|
||||||
|
```sh
|
||||||
|
go get github.com/nobonobo/unqlitego
|
||||||
|
cd $GOPATH/src/github.com/nobonobo/unqlitego
|
||||||
|
git submodule init
|
||||||
|
git submodule update
|
||||||
|
make
|
||||||
|
go install
|
||||||
|
```
|
||||||
|
|
||||||
|
Benchmark
|
||||||
|
----------
|
||||||
|
|
||||||
|
```
|
||||||
|
BenchmarkFileStore 200000 9667 ns/op
|
||||||
|
BenchmarkFileFetch 500000 7928 ns/op
|
||||||
|
BenchmarkMemStore 500000 3824 ns/op
|
||||||
|
BenchmarkMemFetch 1000000 3448 ns/op
|
||||||
|
```
|
||||||
|
|
1
src
Submodule
1
src
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 480271123692090441b41c54d0433218d592da15
|
334
unqlite.go
Normal file
334
unqlite.go
Normal file
|
@ -0,0 +1,334 @@
|
||||||
|
package unqlitego
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo LDFLAGS: -L./ -lunqlite
|
||||||
|
#include "./src/unqlite.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UnQLiteError ... standard error for this module
|
||||||
|
type UnQLiteError int
|
||||||
|
|
||||||
|
func (e UnQLiteError) Error() string {
|
||||||
|
s := errString[e]
|
||||||
|
if s == "" {
|
||||||
|
return fmt.Sprintf("errno %d", int(e))
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// UnQLiteNoMemErr ...
|
||||||
|
UnQLiteNoMemErr UnQLiteError = UnQLiteError(C.UNQLITE_NOMEM)
|
||||||
|
)
|
||||||
|
|
||||||
|
var errString = map[UnQLiteError]string{
|
||||||
|
C.UNQLITE_NOMEM: "Out of memory",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Database ...
|
||||||
|
type Database struct {
|
||||||
|
handle *C.unqlite
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cursor ...
|
||||||
|
type Cursor struct {
|
||||||
|
parent *Database
|
||||||
|
handle *C.unqlite_kv_cursor
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
C.unqlite_lib_init()
|
||||||
|
if C.unqlite_lib_is_threadsafe() != 1 {
|
||||||
|
panic("unqlite library was not compiled for thread-safe option UNQLITE_ENABLE_THREADS=1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDatabase ...
|
||||||
|
func NewDatabase(filename string) (db *Database, err error) {
|
||||||
|
db = &Database{}
|
||||||
|
name := C.CString(filename)
|
||||||
|
defer C.free(unsafe.Pointer(name))
|
||||||
|
res := C.unqlite_open(&db.handle, name, C.UNQLITE_OPEN_CREATE)
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
}
|
||||||
|
if db.handle != nil {
|
||||||
|
runtime.SetFinalizer(db, (*Database).Close)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close ...
|
||||||
|
func (db *Database) Close() (err error) {
|
||||||
|
if db.handle != nil {
|
||||||
|
res := C.unqlite_close(db.handle)
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
}
|
||||||
|
db.handle = nil
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config ...
|
||||||
|
func (db *Database) Config(operate int, args ...interface{}) (err error) {
|
||||||
|
err = errors.New("not implemented")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store ...
|
||||||
|
func (db *Database) Store(key, value []byte) (err error) {
|
||||||
|
res := C.unqlite_kv_store(db.handle,
|
||||||
|
unsafe.Pointer(&key[0]), C.int(len(key)),
|
||||||
|
unsafe.Pointer(&value[0]), C.unqlite_int64(len(value)))
|
||||||
|
if res == C.UNQLITE_OK {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return UnQLiteError(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append ...
|
||||||
|
func (db *Database) Append(key, value []byte) (err error) {
|
||||||
|
res := C.unqlite_kv_append(db.handle,
|
||||||
|
unsafe.Pointer(&key[0]), C.int(len(key)),
|
||||||
|
unsafe.Pointer(&value[0]), C.unqlite_int64(len(value)))
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch ...
|
||||||
|
func (db *Database) Fetch(key []byte) (value []byte, err error) {
|
||||||
|
var n C.unqlite_int64
|
||||||
|
res := C.unqlite_kv_fetch(db.handle, unsafe.Pointer(&key[0]), C.int(len(key)), nil, &n)
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
value = make([]byte, int(n))
|
||||||
|
res = C.unqlite_kv_fetch(db.handle, unsafe.Pointer(&key[0]), C.int(len(key)), unsafe.Pointer(&value[0]), &n)
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete ...
|
||||||
|
func (db *Database) Delete(key []byte) (err error) {
|
||||||
|
res := C.unqlite_kv_delete(db.handle, unsafe.Pointer(&key[0]), C.int(len(key)))
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin ...
|
||||||
|
func (db *Database) Begin() (err error) {
|
||||||
|
res := C.unqlite_begin(db.handle)
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commit ...
|
||||||
|
func (db *Database) Commit() (err error) {
|
||||||
|
res := C.unqlite_commit(db.handle)
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rollback ...
|
||||||
|
func (db *Database) Rollback() (err error) {
|
||||||
|
res := C.unqlite_rollback(db.handle)
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCursor ...
|
||||||
|
func (db *Database) NewCursor() (cursor *Cursor, err error) {
|
||||||
|
cursor = &Cursor{parent: db}
|
||||||
|
res := C.unqlite_kv_cursor_init(db.handle, &cursor.handle)
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
}
|
||||||
|
runtime.SetFinalizer(cursor, (*Cursor).Close)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close ...
|
||||||
|
func (curs *Cursor) Close() (err error) {
|
||||||
|
if curs.parent.handle != nil && curs.handle != nil {
|
||||||
|
res := C.unqlite_kv_cursor_release(curs.parent.handle, curs.handle)
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
}
|
||||||
|
curs.handle = nil
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seek ...
|
||||||
|
func (curs *Cursor) Seek(key []byte) (err error) {
|
||||||
|
res := C.unqlite_kv_cursor_seek(curs.handle, unsafe.Pointer(&key[0]), C.int(len(key)), C.UNQLITE_CURSOR_MATCH_EXACT)
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// SeekLE ...
|
||||||
|
func (curs *Cursor) SeekLE(key []byte) (err error) {
|
||||||
|
res := C.unqlite_kv_cursor_seek(curs.handle, unsafe.Pointer(&key[0]), C.int(len(key)), C.UNQLITE_CURSOR_MATCH_LE)
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// SeekGE ...
|
||||||
|
func (curs *Cursor) SeekGE(key []byte) (err error) {
|
||||||
|
res := C.unqlite_kv_cursor_seek(curs.handle, unsafe.Pointer(&key[0]), C.int(len(key)), C.UNQLITE_CURSOR_MATCH_GE)
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// First ...
|
||||||
|
func (curs *Cursor) First() (err error) {
|
||||||
|
res := C.unqlite_kv_cursor_first_entry(curs.handle)
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last ...
|
||||||
|
func (curs *Cursor) Last() (err error) {
|
||||||
|
res := C.unqlite_kv_cursor_last_entry(curs.handle)
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsValid ...
|
||||||
|
func (curs *Cursor) IsValid() (ok bool) {
|
||||||
|
return C.unqlite_kv_cursor_valid_entry(curs.handle) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next ...
|
||||||
|
func (curs *Cursor) Next() (err error) {
|
||||||
|
res := C.unqlite_kv_cursor_next_entry(curs.handle)
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prev ...
|
||||||
|
func (curs *Cursor) Prev() (err error) {
|
||||||
|
res := C.unqlite_kv_cursor_prev_entry(curs.handle)
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete ...
|
||||||
|
func (curs *Cursor) Delete() (err error) {
|
||||||
|
res := C.unqlite_kv_cursor_delete_entry(curs.handle)
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset ...
|
||||||
|
func (curs *Cursor) Reset() (err error) {
|
||||||
|
res := C.unqlite_kv_cursor_reset(curs.handle)
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key ...
|
||||||
|
func (curs *Cursor) Key() (key []byte, err error) {
|
||||||
|
var n C.int
|
||||||
|
res := C.unqlite_kv_cursor_key(curs.handle, nil, &n)
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
key = make([]byte, int(n))
|
||||||
|
res = C.unqlite_kv_cursor_key(curs.handle, unsafe.Pointer(&key[0]), &n)
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value ...
|
||||||
|
func (curs *Cursor) Value() (value []byte, err error) {
|
||||||
|
var n C.unqlite_int64
|
||||||
|
res := C.unqlite_kv_cursor_data(curs.handle, nil, &n)
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
value = make([]byte, int(n))
|
||||||
|
res = C.unqlite_kv_cursor_data(curs.handle, unsafe.Pointer(&value[0]), &n)
|
||||||
|
if res != C.UNQLITE_OK {
|
||||||
|
err = UnQLiteError(res)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: implement
|
||||||
|
|
||||||
|
// Database Engine Handle
|
||||||
|
int unqlite_config(unqlite *pDb,int nOp,...);
|
||||||
|
|
||||||
|
// Key/Value (KV) Store Interfaces
|
||||||
|
int unqlite_kv_store_fmt(unqlite *pDb,const void *pKey,int nKeyLen,const char *zFormat,...);
|
||||||
|
int unqlite_kv_append_fmt(unqlite *pDb,const void *pKey,int nKeyLen,const char *zFormat,...);
|
||||||
|
int unqlite_kv_fetch_callback(unqlite *pDb,const void *pKey,
|
||||||
|
int nKeyLen,int (*xConsumer)(const void *,unsigned int,void *),void *pUserData);
|
||||||
|
int unqlite_kv_config(unqlite *pDb,int iOp,...);
|
||||||
|
|
||||||
|
// Cursor Iterator Interfaces
|
||||||
|
int unqlite_kv_cursor_key_callback(unqlite_kv_cursor *pCursor,int (*xConsumer)(const void *,unsigned int,void *),void *pUserData);
|
||||||
|
int unqlite_kv_cursor_data_callback(unqlite_kv_cursor *pCursor,int (*xConsumer)(const void *,unsigned int,void *),void *pUserData);
|
||||||
|
|
||||||
|
// Utility interfaces
|
||||||
|
int unqlite_util_load_mmaped_file(const char *zFile,void **ppMap,unqlite_int64 *pFileSize);
|
||||||
|
int unqlite_util_release_mmaped_file(void *pMap,unqlite_int64 iFileSize);
|
||||||
|
int unqlite_util_random_string(unqlite *pDb,char *zBuf,unsigned int buf_size);
|
||||||
|
unsigned int unqlite_util_random_num(unqlite *pDb);
|
||||||
|
|
||||||
|
// Global Library Management Interfaces
|
||||||
|
int unqlite_lib_config(int nConfigOp,...);
|
||||||
|
int unqlite_lib_init(void);
|
||||||
|
int unqlite_lib_shutdown(void);
|
||||||
|
int unqlite_lib_is_threadsafe(void);
|
||||||
|
const char * unqlite_lib_version(void);
|
||||||
|
const char * unqlite_lib_signature(void);
|
||||||
|
const char * unqlite_lib_ident(void);
|
||||||
|
const char * unqlite_lib_copyright(void);
|
||||||
|
*/
|
131
unqlite_test.go
Normal file
131
unqlite_test.go
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
package unqlitego
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
. "github.com/r7kamura/gospel"
|
||||||
|
"io/ioutil"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Testモジュール(t *testing.T) {
|
||||||
|
var db *Database
|
||||||
|
var src []byte
|
||||||
|
src = []byte("value")
|
||||||
|
|
||||||
|
Describe(t, "正常系", func() {
|
||||||
|
Context("基本テスト", func() {
|
||||||
|
It("NewDatabase", func() {
|
||||||
|
f, err := ioutil.TempFile("", "sample.db")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
db, err = NewDatabase(f.Name())
|
||||||
|
Expect(err).To(NotExist)
|
||||||
|
Expect(db).To(Exist)
|
||||||
|
})
|
||||||
|
It("Database.Begin", func() {
|
||||||
|
err := db.Begin()
|
||||||
|
Expect(err).To(NotExist)
|
||||||
|
})
|
||||||
|
It("Database.Store", func() {
|
||||||
|
err := db.Store([]byte("sample"), src)
|
||||||
|
Expect(err).To(NotExist)
|
||||||
|
})
|
||||||
|
It("Database.Fetch", func() {
|
||||||
|
dst, err := db.Fetch([]byte("sample"))
|
||||||
|
Expect(err).To(NotExist)
|
||||||
|
Expect(bytes.Compare(src, dst)).To(Equal, 0)
|
||||||
|
})
|
||||||
|
It("Database.Append", func() {
|
||||||
|
err1 := db.Append([]byte("sample"), []byte(" append"))
|
||||||
|
Expect(err1).To(NotExist)
|
||||||
|
dst, err2 := db.Fetch([]byte("sample"))
|
||||||
|
Expect(err2).To(NotExist)
|
||||||
|
Expect(bytes.Compare(append(src, []byte(" append")...), dst)).To(Equal, 0)
|
||||||
|
})
|
||||||
|
It("Database.Commit", func() {
|
||||||
|
err := db.Commit()
|
||||||
|
Expect(err).To(NotExist)
|
||||||
|
})
|
||||||
|
It("Database.Begin", func() {
|
||||||
|
err := db.Begin()
|
||||||
|
Expect(err).To(NotExist)
|
||||||
|
})
|
||||||
|
It("Database.Delete", func() {
|
||||||
|
err1 := db.Delete([]byte("sample"))
|
||||||
|
Expect(err1).To(NotExist)
|
||||||
|
_, err2 := db.Fetch([]byte("sample"))
|
||||||
|
Expect(err2).To(Exist)
|
||||||
|
})
|
||||||
|
It("Database.Rollback", func() {
|
||||||
|
err := db.Rollback()
|
||||||
|
Expect(err).To(NotExist)
|
||||||
|
value, err2 := db.Fetch([]byte("sample"))
|
||||||
|
Expect(err2).To(NotExist)
|
||||||
|
Expect(value).To(Exist)
|
||||||
|
})
|
||||||
|
It("Database.NewCursor", func() {
|
||||||
|
cursor, err := db.NewCursor()
|
||||||
|
Expect(err).To(NotExist)
|
||||||
|
Expect(cursor).To(Exist)
|
||||||
|
err = cursor.Seek([]byte("sample"))
|
||||||
|
Expect(err).To(NotExist)
|
||||||
|
})
|
||||||
|
It("Database.Close", func() {
|
||||||
|
err := db.Close()
|
||||||
|
Expect(err).To(NotExist)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkFileStore(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
f, err := ioutil.TempFile("", "sample.db")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
db, _ := NewDatabase(f.Name())
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
db.Store([]byte(fmt.Sprintf("%d", i)), []byte("abcdefghijklmnopabcdefghijklmnopabcdefghijklmnopabcdefghijklmnop"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkFileFetch(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
f, err := ioutil.TempFile("", "sample.db")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
db, _ := NewDatabase(f.Name())
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
db.Store([]byte(fmt.Sprintf("%d", i)), []byte("abcdefghijklmnopabcdefghijklmnopabcdefghijklmnopabcdefghijklmnop"))
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_, _ = db.Fetch([]byte(fmt.Sprintf("%d", i)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMemStore(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
db, _ := NewDatabase("")
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
db.Store([]byte(fmt.Sprintf("%d", i)), []byte("abcdefghijklmnopabcdefghijklmnopabcdefghijklmnopabcdefghijklmnop"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMemFetch(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
db, _ := NewDatabase("")
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
db.Store([]byte(fmt.Sprintf("%d", i)), []byte("abcdefghijklmnopabcdefghijklmnopabcdefghijklmnopabcdefghijklmnop"))
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_, _ = db.Fetch([]byte(fmt.Sprintf("%d", i)))
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue