You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

443 lines
13 KiB

package db
import (
"bytes"
"container/list"
"encoding/binary"
"fmt"
"io/ioutil"
"math/rand"
"os"
"path/filepath"
"reflect"
"testing"
"time"
"github.com/guptarohit/asciigraph"
)
type testKeyType int64
// Simple execution cmd
// go test -run=XXX -bench=. -benchmem -cpuprofile=cpu.out -memprofile=mem.out -timeout 20m -benchtime=1m
var valueLen = 256
var testSetSize = int64(10000000)
var batchSize = 100
// parameters for drawing graph
var graphCountingPeriod = 10000
var graphWidth = 120
var graphHeigh = 20
var deviceType = "ssd"
func init() {
rand.Seed(time.Now().Unix())
}
func int64ToBytes(i testKeyType) []byte {
buf := make([]byte, 8)
binary.BigEndian.PutUint64(buf, uint64(i))
return buf
}
func printGraph(statics list.List) {
if statics.Len() == 0 {
return
}
// convert list to slice
var staticsSlice = make([]float64, statics.Len())
i := 0
for e := statics.Front(); e != nil; e = e.Next() {
staticsSlice[i] = e.Value.(float64)
i++
}
graph := asciigraph.Plot(staticsSlice, asciigraph.Width(graphWidth), asciigraph.Height(graphHeigh))
fmt.Println(graph)
}
func dirSizeKB(path string) (int64, error) {
var size int64
err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
if !info.IsDir() {
size += info.Size()
}
return err
})
return size / 1024, err
}
func BenchmarkRandomWR(b *testing.B) {
// generate a common random data set
internal := map[testKeyType][]byte{}
for i := 0; i < int(testSetSize); i++ {
// generate a random value
token := make([]byte, valueLen)
internal[testKeyType(i)] = token
}
for dbType, dbConstructors := range dbImpls {
// create db
dbName := string(dbType)
tmpDir, _ := ioutil.TempDir("", dbName)
defer os.RemoveAll(tmpDir)
dbInstance, _ := dbConstructors(tmpDir)
var numOfWrite int64
var idx testKeyType
var statics list.List
var startTime time.Time
fmt.Printf("[%s]\ntestset_size: %d\nkey_len: %d\nval_len: %d\n",
dbName, testSetSize, reflect.TypeOf(idx).Size(), valueLen)
fmt.Println("device type: ssd")
// write only
b.Run(dbName+"-write", func(b *testing.B) {
var i int
for i = 0; i < b.N; i++ {
if i != 0 && i%graphCountingPeriod == 0 {
startTime = time.Now()
}
idx = testKeyType((int64(rand.Int()) % testSetSize)) // pick a random key
rand.Read(internal[idx]) // generate a random data
dbInstance.Set(
int64ToBytes(testKeyType(idx)),
internal[idx],
)
if i != 0 && i%graphCountingPeriod == 0 {
endTime := time.Now().Sub(startTime).Seconds()
statics.PushBack(endTime)
}
}
numOfWrite += int64(i)
})
printGraph(statics)
statics.Init()
// read only
b.Run(dbName+"-read", func(b *testing.B) {
for i := 0; i < b.N; i++ {
if i != 0 && i%graphCountingPeriod == 0 {
startTime = time.Now()
}
idx = testKeyType((int64(rand.Int()) % testSetSize))
originalVal := internal[idx]
retrievedVal := dbInstance.Get(int64ToBytes(testKeyType(idx)))
if len(retrievedVal) != 0 {
if len(retrievedVal) != valueLen {
b.Errorf("Expected length %X for %v, got %X",
valueLen, idx, len(retrievedVal))
break
} else if !bytes.Equal(retrievedVal, originalVal) {
b.Errorf("Expected %v for %v, got %v",
originalVal, idx, retrievedVal)
break
}
}
if i != 0 && i%graphCountingPeriod == 0 {
endTime := time.Now().Sub(startTime).Seconds()
statics.PushBack(endTime)
}
}
})
printGraph(statics)
statics.Init()
// write and read
b.Run(dbName+"-write-read", func(b *testing.B) {
var i int
for i = 0; i < b.N; i++ {
if i != 0 && i%graphCountingPeriod == 0 {
startTime = time.Now()
}
idx = testKeyType(int64(rand.Int()) % testSetSize) // pick a random key
rand.Read(internal[idx]) // generate a random data
dbInstance.Set(
int64ToBytes(testKeyType(idx)),
internal[idx],
)
originalVal := internal[idx]
retrievedVal := dbInstance.Get(int64ToBytes(testKeyType(idx)))
if len(retrievedVal) != 0 {
if len(retrievedVal) != valueLen {
b.Errorf("Expected length %X for %v, got %X",
valueLen, idx, len(retrievedVal))
break
} else if !bytes.Equal(retrievedVal, originalVal) {
b.Errorf("Expected %v for %v, got %v",
originalVal, idx, retrievedVal)
break
}
}
if i != 0 && i%graphCountingPeriod == 0 {
endTime := time.Now().Sub(startTime).Seconds()
statics.PushBack(endTime)
}
}
numOfWrite += int64(i)
})
printGraph(statics)
statics.Init()
// close
dbInstance.Close()
size, err := dirSizeKB(tmpDir)
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("* Total size of %s db: %v kb, Size of 1 write: %v byte\n", dbName, size, size*1024/numOfWrite)
}
}
}
func BenchmarkRandomBatchWR(b *testing.B) {
// generate a common random data set
internal := map[testKeyType][]byte{}
for i := 0; i < int(testSetSize); i++ {
// generate a random value
token := make([]byte, valueLen)
internal[testKeyType(i)] = token
}
for dbType, dbConstructors := range dbImpls {
// create db
dbName := string(dbType)
tmpDir, _ := ioutil.TempDir("", dbName)
defer os.RemoveAll(tmpDir)
dbInstance, _ := dbConstructors(tmpDir)
var numOfWrite int64
var idx testKeyType
var statics list.List
var startTime time.Time
fmt.Printf("[%s]\ntestset_size: %d\nkey_len: %d\nval_len: %d\n",
dbName, testSetSize, reflect.TypeOf(idx).Size(), valueLen)
fmt.Println("device type: " + deviceType)
fmt.Printf("batch size: %d\n", batchSize)
// write only
b.Run(dbName+"-batch-write", func(b *testing.B) {
var i int
for i = 0; i < b.N; i++ {
if i != 0 && i%graphCountingPeriod == 0 {
startTime = time.Now()
}
tx := dbInstance.NewTx()
for j := 0; j < batchSize; j++ {
idx = testKeyType((int64(rand.Int()) % testSetSize)) // pick a random key
rand.Read(internal[idx]) // generate a random data
tx.Set(
int64ToBytes(testKeyType(idx)),
internal[idx],
)
}
tx.Commit()
if i != 0 && i%graphCountingPeriod == 0 {
endTime := time.Now().Sub(startTime).Seconds()
statics.PushBack(endTime)
}
}
numOfWrite += int64(i)
})
// print a graph
printGraph(statics)
statics.Init()
// read only
b.Run(dbName+"-read", func(b *testing.B) {
for i := 0; i < b.N; i++ {
if i != 0 && i%graphCountingPeriod == 0 {
startTime = time.Now()
}
idx = testKeyType((int64(rand.Int()) % testSetSize))
originalVal := internal[idx]
retrievedVal := dbInstance.Get(int64ToBytes(testKeyType(idx)))
if len(retrievedVal) != 0 {
if len(retrievedVal) != valueLen {
b.Errorf("Expected length %X for %v, got %X",
valueLen, idx, len(retrievedVal))
break
} else if !bytes.Equal(retrievedVal, originalVal) {
b.Errorf("Expected %v for %v, got %v",
originalVal, idx, retrievedVal)
break
}
}
if i != 0 && i%graphCountingPeriod == 0 {
endTime := time.Now().Sub(startTime).Seconds()
statics.PushBack(endTime)
}
}
})
// close
dbInstance.Close()
printGraph(statics)
size, err := dirSizeKB(tmpDir)
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("* Total size of %s db: %v kb, Size of 1 write: %v byte\n", dbName, size, size*1024/numOfWrite)
}
}
}
/*
[Refined Test Result]
goos: windows
goarch: amd64
pkg: github.com/aergoio/aergo-lib/db
[badgerdb-ssd-single]
testset_size: 10000000
key_len: 8
val_len: 256
device type: ssd
BenchmarkRandomWR/badgerdb-write-12 30000000 29536 ns/op 4983 B/op 84 allocs/op
BenchmarkRandomWR/badgerdb-read-12 20000000 47739 ns/op 13154 B/op 60 allocs/op
BenchmarkRandomWR/badgerdb-write-read-12 20000000 41990 ns/op 10317 B/op 140 allocs/op
* Total size of badgerdb db: 14544473 kb, Size of 1 write: 286 byte
[leveldb-ssd-single]
testset_size: 10000000
key_len: 8
val_len: 256
device type: ssd
BenchmarkRandomWR/leveldb-write-12 1000000 1006445 ns/op 532 B/op 5 allocs/op
BenchmarkRandomWR/leveldb-read-12 50000000 18941 ns/op 1160 B/op 17 allocs/op
BenchmarkRandomWR/leveldb-write-read-12 1000000 986440 ns/op 1272 B/op 11 allocs/op
* Total size of leveldb db: 567386 kb, Size of 1 write: 250 byte
[badgerdb-ssd-batch100]
testset_size: 10000000
key_len: 8
val_len: 256
device type: ssd
batch size: 100
BenchmarkRandomBatchWR/badgerdb-batch-write-12 2000000 612737 ns/op 383751 B/op 4576 allocs/op
BenchmarkRandomBatchWR/badgerdb-read-12 20000000 53298 ns/op 22177 B/op 71 allocs/op
* Total size of badgerdb db: 74546912 kb, Size of 1 write: 25359 byte
[leveldb-ssd-batch100]
testset_size: 10000000
key_len: 8
val_len: 256
device type: ssd
batch size: 100
BenchmarkRandomBatchWR/leveldb-batch-write-12 300000 6778458 ns/op 127466 B/op 399 allocs/op
BenchmarkRandomBatchWR/leveldb-read-12 5000000 141176 ns/op 4547 B/op 34 allocs/op
* Total size of leveldb db: 2540271 kb, Size of 1 write: 8388 byte
[badgerdb-ssd-batch1000]
testset_size: 10000000
key_len: 8
val_len: 256
device type: ssd
batch size: 1000
BenchmarkRandomBatchWR1000/badgerdb-batch-write-12 200000 5507060 ns/op 3504344 B/op 42743 allocs/op
BenchmarkRandomBatchWR1000/badgerdb-read-12 20000000 52636 ns/op 21867 B/op 73 allocs/op
* Total size of badgerdb db: 51315516 kb, Size of 1 write: 250103 byte
[leveldb-ssd-batch100]
testset_size: 10000000
key_len: 8
val_len: 256
device type: ssd
batch size: 1000
BenchmarkRandomBatchWR1000/leveldb-batch-write-12 20000 70431430 ns/op 1081956 B/op 3906 allocs/op
BenchmarkRandomBatchWR1000/leveldb-read-12 5000000 138074 ns/op 4194 B/op 33 allocs/op
* Total size of leveldb db: 2529393 kb, Size of 1 write: 86046 byte
[badgerdb-hdd-single]
testset_size: 10000000
key_len: 8
val_len: 256
device type: hdd
BenchmarkHddRandomWR/badgerdb-write-12 30000000 27901 ns/op 4809 B/op 82 allocs/op
BenchmarkHddRandomWR/badgerdb-read-12 20000000 45765 ns/op 14321 B/op 68 allocs/op
BenchmarkHddRandomWR/badgerdb-write-read-12 20000000 39404 ns/op 8693 B/op 124 allocs/op
* Total size of badgerdb db: 14697136 kb, Size of 1 write: 289 byte
[leveldb-hdd-single]
testset_size: 10000000
key_len: 8
val_len: 256
device type: hdd
BenchmarkHddRandomWR/leveldb-write-12 50000 20975160 ns/op 551 B/op 4 allocs/op
BenchmarkHddRandomWR/leveldb-read-12 100000000 10375 ns/op 988 B/op 14 allocs/op
BenchmarkHddRandomWR/leveldb-write-read-12 50000 21144257 ns/op 994 B/op 9 allocs/op
* Total size of leveldb db: 31940 kb, Size of 1 write: 272 byte
[badgerdb-hdd-batch100]
testset_size: 10000000
key_len: 8
val_len: 256
device type: hdd
batch size: 100
BenchmarkHddRandomBatchWR/badgerdb-batch-write-12 1000000 675351 ns/op 329398 B/op 4007 allocs/op
BenchmarkHddRandomBatchWR/badgerdb-read-12 10000000 87933 ns/op 22713 B/op 85 allocs/op
* Total size of badgerdb db: 24285947 kb, Size of 1 write: 24620 byte
[leveldb-hdd-batch100]
testset_size: 10000000
key_len: 8
val_len: 256
device type: hdd
batch size: 100
BenchmarkHddRandomBatchWR/leveldb-batch-write-12 30000 45769594 ns/op 136783 B/op 399 allocs/op
BenchmarkHddRandomBatchWR/leveldb-read-12 20000000 30579 ns/op 3386 B/op 19 allocs/op
* Total size of leveldb db: 878403 kb, Size of 1 write: 22430 byte
[badgerdb-hdd-batch1000]
testset_size: 10000000
key_len: 8
val_len: 256
device type: hdd
batch size: 1000
BenchmarkHddRandomBatchWR1000/badgerdb-batch-write-12 200000 6599637 ns/op 3724911 B/op 43392 allocs/op
BenchmarkHddRandomBatchWR1000/badgerdb-read-12 10000000 99201 ns/op 31710 B/op 105 allocs/op
* Total size of badgerdb db: 51157857 kb, Size of 1 write: 249335 byte
[leveldb-hdd-batch1000]
testset_size: 10000000
key_len: 8
val_len: 256
device type: hdd
batch size: 1000
BenchmarkHddRandomBatchWR1000/leveldb-batch-write-12 10000 209360868 ns/op 1027546 B/op 3363 allocs/op
BenchmarkHddRandomBatchWR1000/leveldb-read-12 10000000 87929 ns/op 3971 B/op 29 allocs/op
* Total size of leveldb db: 1689120 kb, Size of 1 write: 171236 byte
PASS
ok github.com/aergoio/aergo-lib/db 33617.451s
*/