asmt/db/perf_test.go
db/perf_test.goRaw
1package db
2
3import (
4 "bytes"
5 "container/list"
6 "encoding/binary"
7 "fmt"
8 "io/ioutil"
9 "math/rand"
10 "os"
11 "path/filepath"
12 "reflect"
13 "testing"
14 "time"
15
16 "github.com/guptarohit/asciigraph"
17)
18
19type testKeyType int64
20
21// Simple execution cmd
22// go test -run=XXX -bench=. -benchmem -cpuprofile=cpu.out -memprofile=mem.out -timeout 20m -benchtime=1m
23
24var valueLen = 256
25var testSetSize = int64(10000000)
26var batchSize = 100
27
28// parameters for drawing graph
29var graphCountingPeriod = 10000
30var graphWidth = 120
31var graphHeigh = 20
32
33var deviceType = "ssd"
34
35func init() {
36 rand.Seed(time.Now().Unix())
37}
38
39func int64ToBytes(i testKeyType) []byte {
40 buf := make([]byte, 8)
41 binary.BigEndian.PutUint64(buf, uint64(i))
42 return buf
43}
44
45func printGraph(statics list.List) {
46 if statics.Len() == 0 {
47 return
48 }
49 // convert list to slice
50 var staticsSlice = make([]float64, statics.Len())
51 i := 0
52 for e := statics.Front(); e != nil; e = e.Next() {
53 staticsSlice[i] = e.Value.(float64)
54 i++
55 }
56
57 graph := asciigraph.Plot(staticsSlice, asciigraph.Width(graphWidth), asciigraph.Height(graphHeigh))
58 fmt.Println(graph)
59}
60
61func dirSizeKB(path string) (int64, error) {
62 var size int64
63 err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
64 if !info.IsDir() {
65 size += info.Size()
66 }
67 return err
68 })
69 return size / 1024, err
70}
71
72func BenchmarkRandomWR(b *testing.B) {
73
74 // generate a common random data set
75 internal := map[testKeyType][]byte{}
76 for i := 0; i < int(testSetSize); i++ {
77 // generate a random value
78 token := make([]byte, valueLen)
79 internal[testKeyType(i)] = token
80 }
81
82 for dbType, dbConstructors := range dbImpls {
83
84 // create db
85 dbName := string(dbType)
86 tmpDir, _ := ioutil.TempDir("", dbName)
87 defer os.RemoveAll(tmpDir)
88
89 dbInstance, _ := dbConstructors(tmpDir)
90 var numOfWrite int64
91 var idx testKeyType
92 var statics list.List
93 var startTime time.Time
94
95 fmt.Printf("[%s]\ntestset_size: %d\nkey_len: %d\nval_len: %d\n",
96 dbName, testSetSize, reflect.TypeOf(idx).Size(), valueLen)
97 fmt.Println("device type: ssd")
98
99 // write only
100 b.Run(dbName+"-write", func(b *testing.B) {
101 var i int
102 for i = 0; i < b.N; i++ {
103 if i != 0 && i%graphCountingPeriod == 0 {
104 startTime = time.Now()
105 }
106 idx = testKeyType((int64(rand.Int()) % testSetSize)) // pick a random key
107 rand.Read(internal[idx]) // generate a random data
108
109 dbInstance.Set(
110 int64ToBytes(testKeyType(idx)),
111 internal[idx],
112 )
113 if i != 0 && i%graphCountingPeriod == 0 {
114 endTime := time.Now().Sub(startTime).Seconds()
115 statics.PushBack(endTime)
116 }
117 }
118 numOfWrite += int64(i)
119 })
120
121 printGraph(statics)
122 statics.Init()
123
124 // read only
125 b.Run(dbName+"-read", func(b *testing.B) {
126 for i := 0; i < b.N; i++ {
127 if i != 0 && i%graphCountingPeriod == 0 {
128 startTime = time.Now()
129 }
130 idx = testKeyType((int64(rand.Int()) % testSetSize))
131 originalVal := internal[idx]
132
133 retrievedVal := dbInstance.Get(int64ToBytes(testKeyType(idx)))
134
135 if len(retrievedVal) != 0 {
136 if len(retrievedVal) != valueLen {
137 b.Errorf("Expected length %X for %v, got %X",
138 valueLen, idx, len(retrievedVal))
139 break
140 } else if !bytes.Equal(retrievedVal, originalVal) {
141 b.Errorf("Expected %v for %v, got %v",
142 originalVal, idx, retrievedVal)
143 break
144 }
145 }
146
147 if i != 0 && i%graphCountingPeriod == 0 {
148 endTime := time.Now().Sub(startTime).Seconds()
149 statics.PushBack(endTime)
150 }
151 }
152 })
153
154 printGraph(statics)
155 statics.Init()
156
157 // write and read
158 b.Run(dbName+"-write-read", func(b *testing.B) {
159 var i int
160 for i = 0; i < b.N; i++ {
161 if i != 0 && i%graphCountingPeriod == 0 {
162 startTime = time.Now()
163 }
164 idx = testKeyType(int64(rand.Int()) % testSetSize) // pick a random key
165 rand.Read(internal[idx]) // generate a random data
166
167 dbInstance.Set(
168 int64ToBytes(testKeyType(idx)),
169 internal[idx],
170 )
171
172 originalVal := internal[idx]
173
174 retrievedVal := dbInstance.Get(int64ToBytes(testKeyType(idx)))
175
176 if len(retrievedVal) != 0 {
177 if len(retrievedVal) != valueLen {
178 b.Errorf("Expected length %X for %v, got %X",
179 valueLen, idx, len(retrievedVal))
180 break
181 } else if !bytes.Equal(retrievedVal, originalVal) {
182 b.Errorf("Expected %v for %v, got %v",
183 originalVal, idx, retrievedVal)
184 break
185 }
186 }
187
188 if i != 0 && i%graphCountingPeriod == 0 {
189 endTime := time.Now().Sub(startTime).Seconds()
190 statics.PushBack(endTime)
191 }
192 }
193 numOfWrite += int64(i)
194 })
195
196 printGraph(statics)
197 statics.Init()
198
199 // close
200 dbInstance.Close()
201
202 size, err := dirSizeKB(tmpDir)
203 if err != nil {
204 fmt.Println(err)
205 } else {
206 fmt.Printf("* Total size of %s db: %v kb, Size of 1 write: %v byte\n", dbName, size, size*1024/numOfWrite)
207 }
208 }
209}
210
211func BenchmarkRandomBatchWR(b *testing.B) {
212
213 // generate a common random data set
214 internal := map[testKeyType][]byte{}
215 for i := 0; i < int(testSetSize); i++ {
216 // generate a random value
217 token := make([]byte, valueLen)
218 internal[testKeyType(i)] = token
219 }
220
221 for dbType, dbConstructors := range dbImpls {
222
223 // create db
224 dbName := string(dbType)
225 tmpDir, _ := ioutil.TempDir("", dbName)
226 defer os.RemoveAll(tmpDir)
227
228 dbInstance, _ := dbConstructors(tmpDir)
229 var numOfWrite int64
230 var idx testKeyType
231 var statics list.List
232 var startTime time.Time
233
234 fmt.Printf("[%s]\ntestset_size: %d\nkey_len: %d\nval_len: %d\n",
235 dbName, testSetSize, reflect.TypeOf(idx).Size(), valueLen)
236 fmt.Println("device type: " + deviceType)
237 fmt.Printf("batch size: %d\n", batchSize)
238
239 // write only
240 b.Run(dbName+"-batch-write", func(b *testing.B) {
241 var i int
242
243 for i = 0; i < b.N; i++ {
244 if i != 0 && i%graphCountingPeriod == 0 {
245 startTime = time.Now()
246 }
247 tx := dbInstance.NewTx()
248
249 for j := 0; j < batchSize; j++ {
250 idx = testKeyType((int64(rand.Int()) % testSetSize)) // pick a random key
251 rand.Read(internal[idx]) // generate a random data
252
253 tx.Set(
254 int64ToBytes(testKeyType(idx)),
255 internal[idx],
256 )
257 }
258 tx.Commit()
259 if i != 0 && i%graphCountingPeriod == 0 {
260 endTime := time.Now().Sub(startTime).Seconds()
261 statics.PushBack(endTime)
262 }
263 }
264 numOfWrite += int64(i)
265 })
266
267 // print a graph
268 printGraph(statics)
269 statics.Init()
270
271 // read only
272 b.Run(dbName+"-read", func(b *testing.B) {
273 for i := 0; i < b.N; i++ {
274 if i != 0 && i%graphCountingPeriod == 0 {
275 startTime = time.Now()
276 }
277
278 idx = testKeyType((int64(rand.Int()) % testSetSize))
279 originalVal := internal[idx]
280
281 retrievedVal := dbInstance.Get(int64ToBytes(testKeyType(idx)))
282
283 if len(retrievedVal) != 0 {
284 if len(retrievedVal) != valueLen {
285 b.Errorf("Expected length %X for %v, got %X",
286 valueLen, idx, len(retrievedVal))
287 break
288 } else if !bytes.Equal(retrievedVal, originalVal) {
289 b.Errorf("Expected %v for %v, got %v",
290 originalVal, idx, retrievedVal)
291 break
292 }
293 }
294 if i != 0 && i%graphCountingPeriod == 0 {
295 endTime := time.Now().Sub(startTime).Seconds()
296 statics.PushBack(endTime)
297 }
298 }
299 })
300
301 // close
302 dbInstance.Close()
303
304 printGraph(statics)
305
306 size, err := dirSizeKB(tmpDir)
307 if err != nil {
308 fmt.Println(err)
309 } else {
310 fmt.Printf("* Total size of %s db: %v kb, Size of 1 write: %v byte\n", dbName, size, size*1024/numOfWrite)
311 }
312 }
313}
314
315/*
316[Refined Test Result]
317goos: windows
318goarch: amd64
319pkg: github.com/aergoio/aergo-lib/db
320
321[badgerdb-ssd-single]
322testset_size: 10000000
323key_len: 8
324val_len: 256
325device type: ssd
326BenchmarkRandomWR/badgerdb-write-12 30000000 29536 ns/op 4983 B/op 84 allocs/op
327BenchmarkRandomWR/badgerdb-read-12 20000000 47739 ns/op 13154 B/op 60 allocs/op
328BenchmarkRandomWR/badgerdb-write-read-12 20000000 41990 ns/op 10317 B/op 140 allocs/op
329* Total size of badgerdb db: 14544473 kb, Size of 1 write: 286 byte
330
331[leveldb-ssd-single]
332testset_size: 10000000
333key_len: 8
334val_len: 256
335device type: ssd
336BenchmarkRandomWR/leveldb-write-12 1000000 1006445 ns/op 532 B/op 5 allocs/op
337BenchmarkRandomWR/leveldb-read-12 50000000 18941 ns/op 1160 B/op 17 allocs/op
338BenchmarkRandomWR/leveldb-write-read-12 1000000 986440 ns/op 1272 B/op 11 allocs/op
339* Total size of leveldb db: 567386 kb, Size of 1 write: 250 byte
340
341[badgerdb-ssd-batch100]
342testset_size: 10000000
343key_len: 8
344val_len: 256
345device type: ssd
346batch size: 100
347BenchmarkRandomBatchWR/badgerdb-batch-write-12 2000000 612737 ns/op 383751 B/op 4576 allocs/op
348BenchmarkRandomBatchWR/badgerdb-read-12 20000000 53298 ns/op 22177 B/op 71 allocs/op
349* Total size of badgerdb db: 74546912 kb, Size of 1 write: 25359 byte
350
351[leveldb-ssd-batch100]
352testset_size: 10000000
353key_len: 8
354val_len: 256
355device type: ssd
356batch size: 100
357BenchmarkRandomBatchWR/leveldb-batch-write-12 300000 6778458 ns/op 127466 B/op 399 allocs/op
358BenchmarkRandomBatchWR/leveldb-read-12 5000000 141176 ns/op 4547 B/op 34 allocs/op
359* Total size of leveldb db: 2540271 kb, Size of 1 write: 8388 byte
360
361[badgerdb-ssd-batch1000]
362testset_size: 10000000
363key_len: 8
364val_len: 256
365device type: ssd
366batch size: 1000
367BenchmarkRandomBatchWR1000/badgerdb-batch-write-12 200000 5507060 ns/op 3504344 B/op 42743 allocs/op
368BenchmarkRandomBatchWR1000/badgerdb-read-12 20000000 52636 ns/op 21867 B/op 73 allocs/op
369* Total size of badgerdb db: 51315516 kb, Size of 1 write: 250103 byte
370
371[leveldb-ssd-batch100]
372testset_size: 10000000
373key_len: 8
374val_len: 256
375device type: ssd
376batch size: 1000
377BenchmarkRandomBatchWR1000/leveldb-batch-write-12 20000 70431430 ns/op 1081956 B/op 3906 allocs/op
378BenchmarkRandomBatchWR1000/leveldb-read-12 5000000 138074 ns/op 4194 B/op 33 allocs/op
379* Total size of leveldb db: 2529393 kb, Size of 1 write: 86046 byte
380
381[badgerdb-hdd-single]
382testset_size: 10000000
383key_len: 8
384val_len: 256
385device type: hdd
386BenchmarkHddRandomWR/badgerdb-write-12 30000000 27901 ns/op 4809 B/op 82 allocs/op
387BenchmarkHddRandomWR/badgerdb-read-12 20000000 45765 ns/op 14321 B/op 68 allocs/op
388BenchmarkHddRandomWR/badgerdb-write-read-12 20000000 39404 ns/op 8693 B/op 124 allocs/op
389* Total size of badgerdb db: 14697136 kb, Size of 1 write: 289 byte
390
391[leveldb-hdd-single]
392testset_size: 10000000
393key_len: 8
394val_len: 256
395device type: hdd
396BenchmarkHddRandomWR/leveldb-write-12 50000 20975160 ns/op 551 B/op 4 allocs/op
397BenchmarkHddRandomWR/leveldb-read-12 100000000 10375 ns/op 988 B/op 14 allocs/op
398BenchmarkHddRandomWR/leveldb-write-read-12 50000 21144257 ns/op 994 B/op 9 allocs/op
399* Total size of leveldb db: 31940 kb, Size of 1 write: 272 byte
400
401[badgerdb-hdd-batch100]
402testset_size: 10000000
403key_len: 8
404val_len: 256
405device type: hdd
406batch size: 100
407BenchmarkHddRandomBatchWR/badgerdb-batch-write-12 1000000 675351 ns/op 329398 B/op 4007 allocs/op
408BenchmarkHddRandomBatchWR/badgerdb-read-12 10000000 87933 ns/op 22713 B/op 85 allocs/op
409* Total size of badgerdb db: 24285947 kb, Size of 1 write: 24620 byte
410
411[leveldb-hdd-batch100]
412testset_size: 10000000
413key_len: 8
414val_len: 256
415device type: hdd
416batch size: 100
417BenchmarkHddRandomBatchWR/leveldb-batch-write-12 30000 45769594 ns/op 136783 B/op 399 allocs/op
418BenchmarkHddRandomBatchWR/leveldb-read-12 20000000 30579 ns/op 3386 B/op 19 allocs/op
419* Total size of leveldb db: 878403 kb, Size of 1 write: 22430 byte
420
421[badgerdb-hdd-batch1000]
422testset_size: 10000000
423key_len: 8
424val_len: 256
425device type: hdd
426batch size: 1000
427BenchmarkHddRandomBatchWR1000/badgerdb-batch-write-12 200000 6599637 ns/op 3724911 B/op 43392 allocs/op
428BenchmarkHddRandomBatchWR1000/badgerdb-read-12 10000000 99201 ns/op 31710 B/op 105 allocs/op
429* Total size of badgerdb db: 51157857 kb, Size of 1 write: 249335 byte
430
431[leveldb-hdd-batch1000]
432testset_size: 10000000
433key_len: 8
434val_len: 256
435device type: hdd
436batch size: 1000
437BenchmarkHddRandomBatchWR1000/leveldb-batch-write-12 10000 209360868 ns/op 1027546 B/op 3363 allocs/op
438BenchmarkHddRandomBatchWR1000/leveldb-read-12 10000000 87929 ns/op 3971 B/op 29 allocs/op
439* Total size of leveldb db: 1689120 kb, Size of 1 write: 171236 byte
440
441PASS
442ok github.com/aergoio/aergo-lib/db 33617.451s
443*/