github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/syndtr/goleveldb/leveldb/bench_test.go (about) 1 // Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com> 2 // All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style license that can be 5 // found in the LICENSE file. 6 7 package leveldb 8 9 import ( 10 "bytes" 11 "fmt" 12 "math/rand" 13 "os" 14 "path/filepath" 15 "runtime" 16 "sync/atomic" 17 "testing" 18 19 "github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/iterator" 20 "github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/opt" 21 "github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/storage" 22 ) 23 24 func randomString(r *rand.Rand, n int) []byte { 25 b := new(bytes.Buffer) 26 for i := 0; i < n; i++ { 27 b.WriteByte(' ' + byte(r.Intn(95))) 28 } 29 return b.Bytes() 30 } 31 32 func compressibleStr(r *rand.Rand, frac float32, n int) []byte { 33 nn := int(float32(n) * frac) 34 rb := randomString(r, nn) 35 b := make([]byte, 0, n+nn) 36 for len(b) < n { 37 b = append(b, rb...) 38 } 39 return b[:n] 40 } 41 42 type valueGen struct { 43 src []byte 44 pos int 45 } 46 47 func newValueGen(frac float32) *valueGen { 48 v := new(valueGen) 49 r := rand.New(rand.NewSource(301)) 50 v.src = make([]byte, 0, 1048576+100) 51 for len(v.src) < 1048576 { 52 v.src = append(v.src, compressibleStr(r, frac, 100)...) 53 } 54 return v 55 } 56 57 func (v *valueGen) get(n int) []byte { 58 if v.pos+n > len(v.src) { 59 v.pos = 0 60 } 61 v.pos += n 62 return v.src[v.pos-n : v.pos] 63 } 64 65 var benchDB = filepath.Join(os.TempDir(), fmt.Sprintf("goleveldbbench-%d", os.Getuid())) 66 67 type dbBench struct { 68 b *testing.B 69 stor storage.Storage 70 db *DB 71 72 o *opt.Options 73 ro *opt.ReadOptions 74 wo *opt.WriteOptions 75 76 keys, values [][]byte 77 } 78 79 func openDBBench(b *testing.B, noCompress bool) *dbBench { 80 _, err := os.Stat(benchDB) 81 if err == nil { 82 err = os.RemoveAll(benchDB) 83 if err != nil { 84 b.Fatal("cannot remove old db: ", err) 85 } 86 } 87 88 p := &dbBench{ 89 b: b, 90 o: &opt.Options{}, 91 ro: &opt.ReadOptions{}, 92 wo: &opt.WriteOptions{}, 93 } 94 p.stor, err = storage.OpenFile(benchDB, false) 95 if err != nil { 96 b.Fatal("cannot open stor: ", err) 97 } 98 if noCompress { 99 p.o.Compression = opt.NoCompression 100 } 101 102 p.db, err = Open(p.stor, p.o) 103 if err != nil { 104 b.Fatal("cannot open db: ", err) 105 } 106 107 runtime.GOMAXPROCS(runtime.NumCPU()) 108 return p 109 } 110 111 func (p *dbBench) reopen() { 112 p.db.Close() 113 var err error 114 p.db, err = Open(p.stor, p.o) 115 if err != nil { 116 p.b.Fatal("Reopen: got error: ", err) 117 } 118 } 119 120 func (p *dbBench) populate(n int) { 121 p.keys, p.values = make([][]byte, n), make([][]byte, n) 122 v := newValueGen(0.5) 123 for i := range p.keys { 124 p.keys[i], p.values[i] = []byte(fmt.Sprintf("%016d", i)), v.get(100) 125 } 126 } 127 128 func (p *dbBench) randomize() { 129 m := len(p.keys) 130 times := m * 2 131 r1, r2 := rand.New(rand.NewSource(0xdeadbeef)), rand.New(rand.NewSource(0xbeefface)) 132 for n := 0; n < times; n++ { 133 i, j := r1.Int()%m, r2.Int()%m 134 if i == j { 135 continue 136 } 137 p.keys[i], p.keys[j] = p.keys[j], p.keys[i] 138 p.values[i], p.values[j] = p.values[j], p.values[i] 139 } 140 } 141 142 func (p *dbBench) writes(perBatch int) { 143 b := p.b 144 db := p.db 145 146 n := len(p.keys) 147 m := n / perBatch 148 if n%perBatch > 0 { 149 m++ 150 } 151 batches := make([]Batch, m) 152 j := 0 153 for i := range batches { 154 first := true 155 for ; j < n && ((j+1)%perBatch != 0 || first); j++ { 156 first = false 157 batches[i].Put(p.keys[j], p.values[j]) 158 } 159 } 160 runtime.GC() 161 162 b.ResetTimer() 163 b.StartTimer() 164 for i := range batches { 165 err := db.Write(&(batches[i]), p.wo) 166 if err != nil { 167 b.Fatal("write failed: ", err) 168 } 169 } 170 b.StopTimer() 171 b.SetBytes(116) 172 } 173 174 func (p *dbBench) gc() { 175 p.keys, p.values = nil, nil 176 runtime.GC() 177 } 178 179 func (p *dbBench) puts() { 180 b := p.b 181 db := p.db 182 183 b.ResetTimer() 184 b.StartTimer() 185 for i := range p.keys { 186 err := db.Put(p.keys[i], p.values[i], p.wo) 187 if err != nil { 188 b.Fatal("put failed: ", err) 189 } 190 } 191 b.StopTimer() 192 b.SetBytes(116) 193 } 194 195 func (p *dbBench) fill() { 196 b := p.b 197 db := p.db 198 199 perBatch := 10000 200 batch := new(Batch) 201 for i, n := 0, len(p.keys); i < n; { 202 first := true 203 for ; i < n && ((i+1)%perBatch != 0 || first); i++ { 204 first = false 205 batch.Put(p.keys[i], p.values[i]) 206 } 207 err := db.Write(batch, p.wo) 208 if err != nil { 209 b.Fatal("write failed: ", err) 210 } 211 batch.Reset() 212 } 213 } 214 215 func (p *dbBench) gets() { 216 b := p.b 217 db := p.db 218 219 b.ResetTimer() 220 for i := range p.keys { 221 _, err := db.Get(p.keys[i], p.ro) 222 if err != nil { 223 b.Error("got error: ", err) 224 } 225 } 226 b.StopTimer() 227 } 228 229 func (p *dbBench) seeks() { 230 b := p.b 231 232 iter := p.newIter() 233 defer iter.Release() 234 b.ResetTimer() 235 for i := range p.keys { 236 if !iter.Seek(p.keys[i]) { 237 b.Error("value not found for: ", string(p.keys[i])) 238 } 239 } 240 b.StopTimer() 241 } 242 243 func (p *dbBench) newIter() iterator.Iterator { 244 iter := p.db.NewIterator(nil, p.ro) 245 err := iter.Error() 246 if err != nil { 247 p.b.Fatal("cannot create iterator: ", err) 248 } 249 return iter 250 } 251 252 func (p *dbBench) close() { 253 if bp, err := p.db.GetProperty("leveldb.blockpool"); err == nil { 254 p.b.Log("Block pool stats: ", bp) 255 } 256 p.db.Close() 257 p.stor.Close() 258 os.RemoveAll(benchDB) 259 p.db = nil 260 p.keys = nil 261 p.values = nil 262 runtime.GC() 263 runtime.GOMAXPROCS(1) 264 } 265 266 func BenchmarkDBWrite(b *testing.B) { 267 p := openDBBench(b, false) 268 p.populate(b.N) 269 p.writes(1) 270 p.close() 271 } 272 273 func BenchmarkDBWriteBatch(b *testing.B) { 274 p := openDBBench(b, false) 275 p.populate(b.N) 276 p.writes(1000) 277 p.close() 278 } 279 280 func BenchmarkDBWriteUncompressed(b *testing.B) { 281 p := openDBBench(b, true) 282 p.populate(b.N) 283 p.writes(1) 284 p.close() 285 } 286 287 func BenchmarkDBWriteBatchUncompressed(b *testing.B) { 288 p := openDBBench(b, true) 289 p.populate(b.N) 290 p.writes(1000) 291 p.close() 292 } 293 294 func BenchmarkDBWriteRandom(b *testing.B) { 295 p := openDBBench(b, false) 296 p.populate(b.N) 297 p.randomize() 298 p.writes(1) 299 p.close() 300 } 301 302 func BenchmarkDBWriteRandomSync(b *testing.B) { 303 p := openDBBench(b, false) 304 p.wo.Sync = true 305 p.populate(b.N) 306 p.writes(1) 307 p.close() 308 } 309 310 func BenchmarkDBOverwrite(b *testing.B) { 311 p := openDBBench(b, false) 312 p.populate(b.N) 313 p.writes(1) 314 p.writes(1) 315 p.close() 316 } 317 318 func BenchmarkDBOverwriteRandom(b *testing.B) { 319 p := openDBBench(b, false) 320 p.populate(b.N) 321 p.writes(1) 322 p.randomize() 323 p.writes(1) 324 p.close() 325 } 326 327 func BenchmarkDBPut(b *testing.B) { 328 p := openDBBench(b, false) 329 p.populate(b.N) 330 p.puts() 331 p.close() 332 } 333 334 func BenchmarkDBRead(b *testing.B) { 335 p := openDBBench(b, false) 336 p.populate(b.N) 337 p.fill() 338 p.gc() 339 340 iter := p.newIter() 341 b.ResetTimer() 342 for iter.Next() { 343 } 344 iter.Release() 345 b.StopTimer() 346 b.SetBytes(116) 347 p.close() 348 } 349 350 func BenchmarkDBReadGC(b *testing.B) { 351 p := openDBBench(b, false) 352 p.populate(b.N) 353 p.fill() 354 355 iter := p.newIter() 356 b.ResetTimer() 357 for iter.Next() { 358 } 359 iter.Release() 360 b.StopTimer() 361 b.SetBytes(116) 362 p.close() 363 } 364 365 func BenchmarkDBReadUncompressed(b *testing.B) { 366 p := openDBBench(b, true) 367 p.populate(b.N) 368 p.fill() 369 p.gc() 370 371 iter := p.newIter() 372 b.ResetTimer() 373 for iter.Next() { 374 } 375 iter.Release() 376 b.StopTimer() 377 b.SetBytes(116) 378 p.close() 379 } 380 381 func BenchmarkDBReadTable(b *testing.B) { 382 p := openDBBench(b, false) 383 p.populate(b.N) 384 p.fill() 385 p.reopen() 386 p.gc() 387 388 iter := p.newIter() 389 b.ResetTimer() 390 for iter.Next() { 391 } 392 iter.Release() 393 b.StopTimer() 394 b.SetBytes(116) 395 p.close() 396 } 397 398 func BenchmarkDBReadReverse(b *testing.B) { 399 p := openDBBench(b, false) 400 p.populate(b.N) 401 p.fill() 402 p.gc() 403 404 iter := p.newIter() 405 b.ResetTimer() 406 iter.Last() 407 for iter.Prev() { 408 } 409 iter.Release() 410 b.StopTimer() 411 b.SetBytes(116) 412 p.close() 413 } 414 415 func BenchmarkDBReadReverseTable(b *testing.B) { 416 p := openDBBench(b, false) 417 p.populate(b.N) 418 p.fill() 419 p.reopen() 420 p.gc() 421 422 iter := p.newIter() 423 b.ResetTimer() 424 iter.Last() 425 for iter.Prev() { 426 } 427 iter.Release() 428 b.StopTimer() 429 b.SetBytes(116) 430 p.close() 431 } 432 433 func BenchmarkDBSeek(b *testing.B) { 434 p := openDBBench(b, false) 435 p.populate(b.N) 436 p.fill() 437 p.seeks() 438 p.close() 439 } 440 441 func BenchmarkDBSeekRandom(b *testing.B) { 442 p := openDBBench(b, false) 443 p.populate(b.N) 444 p.fill() 445 p.randomize() 446 p.seeks() 447 p.close() 448 } 449 450 func BenchmarkDBGet(b *testing.B) { 451 p := openDBBench(b, false) 452 p.populate(b.N) 453 p.fill() 454 p.gets() 455 p.close() 456 } 457 458 func BenchmarkDBGetRandom(b *testing.B) { 459 p := openDBBench(b, false) 460 p.populate(b.N) 461 p.fill() 462 p.randomize() 463 p.gets() 464 p.close() 465 } 466 467 func BenchmarkDBReadConcurrent(b *testing.B) { 468 p := openDBBench(b, false) 469 p.populate(b.N) 470 p.fill() 471 p.gc() 472 defer p.close() 473 474 b.ResetTimer() 475 b.SetBytes(116) 476 477 b.RunParallel(func(pb *testing.PB) { 478 iter := p.newIter() 479 defer iter.Release() 480 for pb.Next() && iter.Next() { 481 } 482 }) 483 } 484 485 func BenchmarkDBReadConcurrent2(b *testing.B) { 486 p := openDBBench(b, false) 487 p.populate(b.N) 488 p.fill() 489 p.gc() 490 defer p.close() 491 492 b.ResetTimer() 493 b.SetBytes(116) 494 495 var dir uint32 496 b.RunParallel(func(pb *testing.PB) { 497 iter := p.newIter() 498 defer iter.Release() 499 if atomic.AddUint32(&dir, 1)%2 == 0 { 500 for pb.Next() && iter.Next() { 501 } 502 } else { 503 if pb.Next() && iter.Last() { 504 for pb.Next() && iter.Prev() { 505 } 506 } 507 } 508 }) 509 }