github.com/moontrade/mdbx-go@v0.4.0/mdbx_test.go (about) 1 package mdbx 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 "os" 7 "strconv" 8 "testing" 9 "unsafe" 10 ) 11 12 func TestChk(t *testing.T) { 13 _, out, err := Chk("-v", "-w", "testdata/12539151/mdbx.dat") 14 if err != nil { 15 t.Fatal(err) 16 } 17 fmt.Println(string(out)) 18 } 19 20 func TestStat(t *testing.T) { 21 _, out, err := Stat("-w", "testdata/75548709/mdbx.dat") 22 if err != nil { 23 t.Fatal(err) 24 } 25 fmt.Println(string(out)) 26 } 27 28 func TestEnv_Open(t *testing.T) { 29 env, err := NewEnv() 30 if err != ErrSuccess { 31 t.Fatal(err) 32 } 33 if err = env.SetGeometry(Geometry{ 34 SizeLower: 1024 * 1024 * 16, 35 SizeNow: 0, 36 SizeUpper: 1024 * 1024 * 1024 * 16, 37 GrowthStep: 1024 * 1024 * 16, 38 ShrinkThreshold: 0, 39 PageSize: 4096, 40 }); err != ErrSuccess { 41 t.Fatal(err) 42 } 43 if err = env.SetMaxDBS(4); err != ErrSuccess { 44 t.Fatal(err) 45 } 46 err = env.Open( 47 "testdata/1", 48 EnvNoTLS|EnvNoReadAhead|EnvCoalesce|EnvLIFOReclaim|EnvSafeNoSync, 49 0664, 50 ) 51 if err != ErrSuccess { 52 t.Fatal(err) 53 } 54 55 var txn Tx 56 if err = env.Begin(&txn, TxReadWrite); err != ErrSuccess { 57 t.Fatal(err) 58 } 59 60 var dbi DBI 61 if dbi, err = txn.OpenDBI("", DBCreate); err != ErrSuccess { 62 t.Fatal(err) 63 } 64 65 key := make([]byte, 8) 66 binary.BigEndian.PutUint64(key, uint64(101)) 67 value := []byte("hello") 68 69 keyVal := Bytes(&key) 70 valueVal := Bytes(&value) 71 72 if err = txn.Put(dbi, &keyVal, &valueVal, 0); err != ErrSuccess { 73 t.Fatal(err) 74 } 75 76 var latency CommitLatency 77 txn.CommitEx(&latency) 78 79 err = env.Close(false) 80 if err != ErrSuccess { 81 t.Fatal(err) 82 } 83 } 84 85 type Engine struct { 86 env *Env 87 rootDB DBI 88 write Tx 89 rd Tx 90 } 91 92 func (engine *Engine) BeginWrite() (*Tx, Error) { 93 engine.write.txn = nil 94 engine.write.env = engine.env 95 return &engine.write, engine.env.Begin(&engine.write, TxReadWrite) 96 } 97 98 func (engine *Engine) BeginRead() (*Tx, Error) { 99 engine.rd.env = engine.env 100 return &engine.rd, engine.rd.Renew() 101 } 102 103 func initDB(path string) (*Engine, Error) { 104 engine := &Engine{} 105 env, err := NewEnv() 106 if err != ErrSuccess { 107 return nil, err 108 } 109 engine.env = env 110 if err = env.SetGeometry(Geometry{ 111 SizeLower: 1024 * 1024 * 16, 112 SizeNow: 1024 * 1024 * 16, 113 SizeUpper: 1024 * 1024 * 1024 * 16, 114 GrowthStep: 1024 * 1024 * 16, 115 ShrinkThreshold: 0, 116 PageSize: 16384, 117 }); err != ErrSuccess { 118 return nil, err 119 } 120 if err = env.SetMaxDBS(1); err != ErrSuccess { 121 return nil, err 122 } 123 124 os.Mkdir("testdata", 0755) 125 err = env.Open( 126 path, 127 //EnvNoMemInit|EnvCoalesce|EnvLIFOReclaim|EnvSyncDurable, 128 EnvNoMemInit|EnvCoalesce|EnvLIFOReclaim|EnvSafeNoSync|EnvWriteMap, 129 0664, 130 ) 131 if err != ErrSuccess { 132 return nil, err 133 } 134 135 if err = env.Begin(&engine.write, TxReadWrite); err != ErrSuccess { 136 return nil, err 137 } 138 139 if engine.rootDB, err = engine.write.OpenDBI("m", DBIntegerKey|DBCreate); err != ErrSuccess { 140 return nil, err 141 } 142 //if engine.rootDB, err = engine.write.OpenDBIEx("m", DBCreate, CmpU64, nil); err != ErrSuccess { 143 // return nil, err 144 //} 145 146 if err = engine.write.Commit(); err != ErrSuccess { 147 return nil, err 148 } 149 150 //if err = env.Begin(&engine.rd, TxReadOnly); err != ErrSuccess { 151 // return nil, err 152 //} 153 //if err = engine.rd.Reset(); err != ErrSuccess { 154 // return nil, err 155 //} 156 157 return engine, ErrSuccess 158 } 159 160 func BenchmarkTxn_Put(b *testing.B) { 161 engine, err := initDB("./testdata/" + strconv.Itoa(b.N)) 162 if err != ErrSuccess { 163 b.Fatal(err) 164 } 165 defer engine.env.Close(true) 166 167 key := make([]byte, 8) 168 data := []byte("hello") 169 170 keyVal := Bytes(&key) 171 dataVal := Bytes(&data) 172 173 b.ResetTimer() 174 b.ReportAllocs() 175 176 txn, err := engine.BeginWrite() 177 if err != ErrSuccess { 178 b.Fatal(err) 179 } 180 181 for i := 0; i < b.N; i++ { 182 //binary.BigEndian.PutUint64(key, uint64(20)) 183 //binary.LittleEndian.PutUint64(key, uint64(i)) 184 *(*uint64)(unsafe.Pointer(keyVal.Base)) = uint64(i) 185 //keyVal = U64(uint64(i)) 186 if err = txn.Put(engine.rootDB, &keyVal, &dataVal, PutAppend); err != ErrSuccess { 187 txn.Abort() 188 b.Fatal(err) 189 } 190 } 191 192 //var envInfo EnvInfo 193 //if err = txn.EnvInfo(&envInfo); err != ErrSuccess { 194 // b.Fatal(err) 195 //} 196 //var info TxInfo 197 //if err = txn.Info(&info); err != ErrSuccess { 198 // b.Fatal(err) 199 //} 200 if err = txn.Commit(); err != ErrSuccess { 201 b.Fatal(err) 202 } 203 //engine.env.Sync(true, false) 204 //engine.env.Sync(true, false) 205 } 206 207 func BenchmarkTxn_PutCursor(b *testing.B) { 208 engine, err := initDB("./testdata/" + strconv.Itoa(b.N)) 209 if err != ErrSuccess { 210 b.Fatal(err) 211 } 212 defer engine.env.Close(true) 213 214 b.ReportAllocs() 215 b.ResetTimer() 216 key := uint64(0) 217 data := []byte("hello") 218 219 keyVal := U64(&key) 220 dataVal := Bytes(&data) 221 222 { 223 insert := func(low, high uint64) { 224 txn, err := engine.BeginWrite() 225 if err != ErrSuccess { 226 b.Fatal(err) 227 } 228 229 cursor, err := txn.OpenCursor(engine.rootDB) 230 if err != ErrSuccess { 231 b.Fatal(err) 232 } 233 234 for i := low; i < high; i++ { 235 key = i 236 if err = cursor.Put(&keyVal, &dataVal, PutAppend); err != ErrSuccess { 237 cursor.Close() 238 txn.Abort() 239 b.Fatal(err) 240 } 241 } 242 243 if err = cursor.Close(); err != ErrSuccess { 244 b.Fatal(err) 245 } 246 if err = txn.Commit(); err != ErrSuccess { 247 b.Fatal(err) 248 } 249 } 250 251 const batchSize = 1000000 252 for i := 0; i < b.N; i += batchSize { 253 end := i + batchSize 254 if end > b.N { 255 end = b.N 256 } 257 insert(uint64(i), uint64(end)) 258 } 259 } 260 } 261 262 func BenchmarkTxn_Get(b *testing.B) { 263 engine, err := initDB("./testdata/" + strconv.Itoa(b.N)) 264 if err != ErrSuccess { 265 b.Fatal(err) 266 } 267 defer engine.env.Close(true) 268 269 key := uint64(0) 270 data := []byte("hello") 271 272 keyVal := U64(&key) 273 dataVal := Bytes(&data) 274 275 { 276 insert := func(low, high uint64) { 277 txn, err := engine.BeginWrite() 278 if err != ErrSuccess { 279 b.Fatal(err) 280 } 281 282 cursor, err := txn.OpenCursor(engine.rootDB) 283 if err != ErrSuccess { 284 b.Fatal(err) 285 } 286 287 for i := low; i < high; i++ { 288 key = i 289 if err = cursor.Put(&keyVal, &dataVal, PutAppend); err != ErrSuccess { 290 cursor.Close() 291 txn.Abort() 292 b.Fatal(err) 293 } 294 } 295 296 if err = cursor.Close(); err != ErrSuccess { 297 b.Fatal(err) 298 } 299 if err = txn.Commit(); err != ErrSuccess { 300 b.Fatal(err) 301 } 302 } 303 304 const batchSize = 10000000 305 for i := 0; i < b.N; i += batchSize { 306 end := i + batchSize 307 if end > b.N { 308 end = b.N 309 } 310 insert(uint64(i), uint64(end)) 311 } 312 } 313 314 txn := &Tx{} 315 316 //engine.env.Sync(true, false) 317 //engine.env.Sync(true, false) 318 319 if err = engine.env.Begin(txn, TxReadOnly); err != ErrSuccess { 320 b.Fatal(err) 321 } 322 b.ResetTimer() 323 b.ReportAllocs() 324 325 //fmt.Println(dataVal.String()) 326 327 //binary.LittleEndian.PutUint64(key, 0) 328 329 count := 0 330 331 for i := 1; i < b.N; i++ { 332 key = uint64(i) 333 keyVal = U64(&key) 334 //binary.BigEndian.PutUint64(key, uint64(20)) 335 //binary.BigEndian.PutUint64(key[8:], uint64(i)) 336 if err = txn.Get(engine.rootDB, &keyVal, &dataVal); err != ErrSuccess && err != ErrNotFound { 337 txn.Reset() 338 b.Fatal(err) 339 } 340 count++ 341 } 342 343 if err = txn.Reset(); err != ErrSuccess { 344 b.Fatal(err) 345 } 346 347 b.StopTimer() 348 349 fmt.Println("count", count) 350 351 //var envInfo EnvInfo 352 //if err = txn.EnvInfo(&envInfo); err != ErrSuccess { 353 // b.Fatal(err) 354 //} 355 //var info TxInfo 356 //if err = txn.Info(&info); err != ErrSuccess { 357 // b.Fatal(err) 358 //} 359 360 //engine.env.Sync(true, false) 361 //engine.env.Sync(true, false) 362 } 363 364 func BenchmarkTxn_GetCursor(b *testing.B) { 365 engine, err := initDB("./testdata/" + strconv.Itoa(b.N)) 366 if err != ErrSuccess { 367 b.Fatal(err) 368 } 369 defer engine.env.Close(true) 370 371 key := uint64(0) 372 data := []byte("hello") 373 374 keyVal := U64(&key) 375 dataVal := Bytes(&data) 376 377 { 378 insert := func(low, high uint64) { 379 txn, err := engine.BeginWrite() 380 if err != ErrSuccess { 381 b.Fatal(err) 382 } 383 384 cursor, err := txn.OpenCursor(engine.rootDB) 385 if err != ErrSuccess { 386 b.Fatal(err) 387 } 388 389 for i := low; i < high; i++ { 390 key = i 391 if err = cursor.Put(&keyVal, &dataVal, PutAppend); err != ErrSuccess { 392 cursor.Close() 393 txn.Abort() 394 b.Fatal(err) 395 } 396 } 397 398 if err = cursor.Close(); err != ErrSuccess { 399 b.Fatal(err) 400 } 401 if err = txn.Commit(); err != ErrSuccess { 402 b.Fatal(err) 403 } 404 } 405 406 const batchSize = 1000000 407 for i := 0; i < b.N; i += batchSize { 408 end := i + batchSize 409 if end > b.N { 410 end = b.N 411 } 412 insert(uint64(i), uint64(end)) 413 } 414 } 415 416 txn := &Tx{} 417 418 //engine.env.Sync(true, false) 419 //engine.env.Sync(true, false) 420 421 if err = engine.env.Begin(txn, TxReadOnly); err != ErrSuccess { 422 b.Fatal(err) 423 } 424 //txn, err = engine.BeginRead() 425 //if err != ErrSuccess { 426 // b.Fatal(err) 427 //} 428 429 b.ResetTimer() 430 b.ReportAllocs() 431 432 cursor, err := txn.OpenCursor(engine.rootDB) 433 if err != ErrSuccess { 434 b.Fatal(err) 435 } 436 437 //binary.LittleEndian.PutUint64(key, uint64(b.N)) 438 439 //if err = txn.Get(engine.rootDB, &keyVal, &dataVal); err != ErrSuccess { 440 // b.Fatal(err) 441 //} 442 443 //keyInt := binary.LittleEndian.Uint64(key) 444 445 //if err = cursor.Get(&keyVal, &dataVal, CursorSet); err != ErrSuccess { 446 // b.Fatal(err) 447 //} 448 449 dataVal = Val{} 450 keyVal = Val{} 451 452 //fmt.Println(dataVal.String()) 453 454 //binary.LittleEndian.PutUint64(key, 0) 455 456 count := 0 457 // 458 for { 459 if err = cursor.Get(&keyVal, &dataVal, CursorNextNoDup); err != ErrSuccess { 460 break 461 } 462 //if keyVal.Base == nil { 463 // break 464 //} 465 count++ 466 //keyInt = binary.LittleEndian.Uint64(key) 467 //_ = keyInt 468 469 //keyVal = Val{} 470 //dataVal = Val{} 471 472 //if cursor.EOF() != 0 { 473 // break 474 //} 475 } 476 477 //if count == 1000000 { 478 // println("1m") 479 //} 480 481 //for i := 0; i < b.N; i++ { 482 // *(*uint64)(unsafe.Pointer(&key[0])) = uint64(i) 483 // //binary.BigEndian.PutUint64(key, uint64(20)) 484 // //binary.BigEndian.PutUint64(key[8:], uint64(i)) 485 // //keyVal = U64(uint64(i)) 486 // if err = txn.Get(engine.rootDB, &keyVal, &dataVal); err != ErrSuccess && err != ErrNotFound { 487 // txn.Reset() 488 // b.Fatal(err) 489 // } 490 //} 491 492 if err = cursor.Close(); err != ErrSuccess { 493 b.Fatal(err) 494 } 495 if err = txn.Reset(); err != ErrSuccess { 496 b.Fatal(err) 497 } 498 499 b.StopTimer() 500 501 fmt.Println("count", count) 502 503 //var envInfo EnvInfo 504 //if err = txn.EnvInfo(&envInfo); err != ErrSuccess { 505 // b.Fatal(err) 506 //} 507 //var info TxInfo 508 //if err = txn.Info(&info); err != ErrSuccess { 509 // b.Fatal(err) 510 //} 511 512 //engine.env.Sync(true, false) 513 //engine.env.Sync(true, false) 514 } 515 516 func TestTxn_Cursor(b *testing.T) { 517 iterations := 100 518 engine, err := initDB("./testdata/" + strconv.Itoa(iterations)) 519 if err != ErrSuccess { 520 b.Fatal(err) 521 } 522 523 key := make([]byte, 8) 524 data := []byte("hello") 525 526 keyVal := Bytes(&key) 527 dataVal := Bytes(&data) 528 529 txn, err := engine.BeginWrite() 530 if err != ErrSuccess { 531 b.Fatal(err) 532 } 533 534 for i := 0; i < iterations; i++ { 535 //binary.BigEndian.PutUint64(key, uint64(20)) 536 //*(*uint64)(unsafe.Pointer(&key[0])) = uint64(i) 537 binary.LittleEndian.PutUint64(key, uint64(i)) 538 //keyVal = U64(uint64(i)) 539 if err = txn.Put(engine.rootDB, &keyVal, &dataVal, 0); err != ErrSuccess { 540 txn.Abort() 541 b.Fatal(err) 542 } 543 } 544 545 //*(*uint64)(unsafe.Pointer(&key[0])) = 0 546 547 if err = txn.Commit(); err != ErrSuccess { 548 b.Fatal(err) 549 } 550 551 txn = &Tx{} 552 553 //engine.env.Sync(true, false) 554 //engine.env.Sync(true, false) 555 556 if err = engine.env.Begin(txn, TxReadOnly); err != ErrSuccess { 557 b.Fatal(err) 558 } 559 //txn, err = engine.BeginRead() 560 //if err != ErrSuccess { 561 // b.Fatal(err) 562 //} 563 564 cursor, err := txn.OpenCursor(engine.rootDB) 565 if err != ErrSuccess { 566 b.Fatal(err) 567 } 568 569 dataVal = Val{} 570 keyVal = Val{} 571 572 binary.LittleEndian.PutUint64(key, 0) 573 574 count := 0 575 // 576 for { 577 if err = cursor.Get(&keyVal, &dataVal, CursorNextNoDup); err != ErrSuccess { 578 break 579 } 580 //if keyVal.Base == nil { 581 // break 582 //} 583 count++ 584 keyInt := keyVal.U64() 585 println("key", keyInt) 586 _ = keyInt 587 588 //keyVal = Val{} 589 //dataVal = Val{} 590 591 //if cursor.EOF() != 0 { 592 // break 593 //} 594 } 595 596 //for i := 0; i < b.N; i++ { 597 // *(*uint64)(unsafe.Pointer(&key[0])) = uint64(i) 598 // //binary.BigEndian.PutUint64(key, uint64(20)) 599 // //binary.BigEndian.PutUint64(key[8:], uint64(i)) 600 // //keyVal = U64(uint64(i)) 601 // if err = txn.Get(engine.rootDB, &keyVal, &dataVal); err != ErrSuccess && err != ErrNotFound { 602 // txn.Reset() 603 // b.Fatal(err) 604 // } 605 //} 606 607 if err = cursor.Close(); err != ErrSuccess { 608 b.Fatal(err) 609 } 610 if err = txn.Reset(); err != ErrSuccess { 611 b.Fatal(err) 612 } 613 614 fmt.Println("count", count) 615 616 //var envInfo EnvInfo 617 //if err = txn.EnvInfo(&envInfo); err != ErrSuccess { 618 // b.Fatal(err) 619 //} 620 //var info TxInfo 621 //if err = txn.Info(&info); err != ErrSuccess { 622 // b.Fatal(err) 623 //} 624 625 //engine.env.Sync(true, false) 626 //engine.env.Sync(true, false) 627 }