arnaucube
arnaucube/asmtPublic Self-hosted repository
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*/