gitlab.com/yannislg/go-pulse@v0.0.0-20210722055913-a3e24e95638d/core/state/snapshot/iterator_test.go (about) 1 // Copyright 2019 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package snapshot 18 19 import ( 20 "bytes" 21 "encoding/binary" 22 "fmt" 23 "math/rand" 24 "testing" 25 26 "github.com/VictoriaMetrics/fastcache" 27 "github.com/ethereum/go-ethereum/common" 28 "github.com/ethereum/go-ethereum/core/rawdb" 29 ) 30 31 // TestAccountIteratorBasics tests some simple single-layer iteration 32 func TestAccountIteratorBasics(t *testing.T) { 33 var ( 34 destructs = make(map[common.Hash]struct{}) 35 accounts = make(map[common.Hash][]byte) 36 storage = make(map[common.Hash]map[common.Hash][]byte) 37 ) 38 // Fill up a parent 39 for i := 0; i < 100; i++ { 40 h := randomHash() 41 data := randomAccount() 42 43 accounts[h] = data 44 if rand.Intn(4) == 0 { 45 destructs[h] = struct{}{} 46 } 47 if rand.Intn(2) == 0 { 48 accStorage := make(map[common.Hash][]byte) 49 value := make([]byte, 32) 50 rand.Read(value) 51 accStorage[randomHash()] = value 52 storage[h] = accStorage 53 } 54 } 55 // Add some (identical) layers on top 56 parent := newDiffLayer(emptyLayer(), common.Hash{}, copyDestructs(destructs), copyAccounts(accounts), copyStorage(storage)) 57 it := parent.AccountIterator(common.Hash{}) 58 verifyIterator(t, 100, it) 59 } 60 61 type testIterator struct { 62 values []byte 63 } 64 65 func newTestIterator(values ...byte) *testIterator { 66 return &testIterator{values} 67 } 68 69 func (ti *testIterator) Seek(common.Hash) { 70 panic("implement me") 71 } 72 73 func (ti *testIterator) Next() bool { 74 ti.values = ti.values[1:] 75 return len(ti.values) > 0 76 } 77 78 func (ti *testIterator) Error() error { 79 return nil 80 } 81 82 func (ti *testIterator) Hash() common.Hash { 83 return common.BytesToHash([]byte{ti.values[0]}) 84 } 85 86 func (ti *testIterator) Account() []byte { 87 return nil 88 } 89 90 func (ti *testIterator) Release() {} 91 92 func TestFastIteratorBasics(t *testing.T) { 93 type testCase struct { 94 lists [][]byte 95 expKeys []byte 96 } 97 for i, tc := range []testCase{ 98 {lists: [][]byte{{0, 1, 8}, {1, 2, 8}, {2, 9}, {4}, 99 {7, 14, 15}, {9, 13, 15, 16}}, 100 expKeys: []byte{0, 1, 2, 4, 7, 8, 9, 13, 14, 15, 16}}, 101 {lists: [][]byte{{0, 8}, {1, 2, 8}, {7, 14, 15}, {8, 9}, 102 {9, 10}, {10, 13, 15, 16}}, 103 expKeys: []byte{0, 1, 2, 7, 8, 9, 10, 13, 14, 15, 16}}, 104 } { 105 var iterators []*weightedAccountIterator 106 for i, data := range tc.lists { 107 it := newTestIterator(data...) 108 iterators = append(iterators, &weightedAccountIterator{it, i}) 109 110 } 111 fi := &fastAccountIterator{ 112 iterators: iterators, 113 initiated: false, 114 } 115 count := 0 116 for fi.Next() { 117 if got, exp := fi.Hash()[31], tc.expKeys[count]; exp != got { 118 t.Errorf("tc %d, [%d]: got %d exp %d", i, count, got, exp) 119 } 120 count++ 121 } 122 } 123 } 124 125 func verifyIterator(t *testing.T, expCount int, it AccountIterator) { 126 t.Helper() 127 128 var ( 129 count = 0 130 last = common.Hash{} 131 ) 132 for it.Next() { 133 hash := it.Hash() 134 if bytes.Compare(last[:], hash[:]) >= 0 { 135 t.Errorf("wrong order: %x >= %x", last, hash) 136 } 137 if it.Account() == nil { 138 t.Errorf("iterator returned nil-value for hash %x", hash) 139 } 140 count++ 141 } 142 if count != expCount { 143 t.Errorf("iterator count mismatch: have %d, want %d", count, expCount) 144 } 145 if err := it.Error(); err != nil { 146 t.Errorf("iterator failed: %v", err) 147 } 148 } 149 150 // TestAccountIteratorTraversal tests some simple multi-layer iteration. 151 func TestAccountIteratorTraversal(t *testing.T) { 152 // Create an empty base layer and a snapshot tree out of it 153 base := &diskLayer{ 154 diskdb: rawdb.NewMemoryDatabase(), 155 root: common.HexToHash("0x01"), 156 cache: fastcache.New(1024 * 500), 157 } 158 snaps := &Tree{ 159 layers: map[common.Hash]snapshot{ 160 base.root: base, 161 }, 162 } 163 // Stack three diff layers on top with various overlaps 164 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, 165 randomAccountSet("0xaa", "0xee", "0xff", "0xf0"), nil) 166 167 snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, 168 randomAccountSet("0xbb", "0xdd", "0xf0"), nil) 169 170 snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, 171 randomAccountSet("0xcc", "0xf0", "0xff"), nil) 172 173 // Verify the single and multi-layer iterators 174 head := snaps.Snapshot(common.HexToHash("0x04")) 175 176 verifyIterator(t, 3, head.(snapshot).AccountIterator(common.Hash{})) 177 verifyIterator(t, 7, head.(*diffLayer).newBinaryAccountIterator()) 178 179 it, _ := snaps.AccountIterator(common.HexToHash("0x04"), common.Hash{}) 180 defer it.Release() 181 182 verifyIterator(t, 7, it) 183 } 184 185 // TestAccountIteratorTraversalValues tests some multi-layer iteration, where we 186 // also expect the correct values to show up. 187 func TestAccountIteratorTraversalValues(t *testing.T) { 188 // Create an empty base layer and a snapshot tree out of it 189 base := &diskLayer{ 190 diskdb: rawdb.NewMemoryDatabase(), 191 root: common.HexToHash("0x01"), 192 cache: fastcache.New(1024 * 500), 193 } 194 snaps := &Tree{ 195 layers: map[common.Hash]snapshot{ 196 base.root: base, 197 }, 198 } 199 // Create a batch of account sets to seed subsequent layers with 200 var ( 201 a = make(map[common.Hash][]byte) 202 b = make(map[common.Hash][]byte) 203 c = make(map[common.Hash][]byte) 204 d = make(map[common.Hash][]byte) 205 e = make(map[common.Hash][]byte) 206 f = make(map[common.Hash][]byte) 207 g = make(map[common.Hash][]byte) 208 h = make(map[common.Hash][]byte) 209 ) 210 for i := byte(2); i < 0xff; i++ { 211 a[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 0, i)) 212 if i > 20 && i%2 == 0 { 213 b[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 1, i)) 214 } 215 if i%4 == 0 { 216 c[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 2, i)) 217 } 218 if i%7 == 0 { 219 d[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 3, i)) 220 } 221 if i%8 == 0 { 222 e[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 4, i)) 223 } 224 if i > 50 || i < 85 { 225 f[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 5, i)) 226 } 227 if i%64 == 0 { 228 g[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 6, i)) 229 } 230 if i%128 == 0 { 231 h[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 7, i)) 232 } 233 } 234 // Assemble a stack of snapshots from the account layers 235 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, a, nil) 236 snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, b, nil) 237 snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, c, nil) 238 snaps.Update(common.HexToHash("0x05"), common.HexToHash("0x04"), nil, d, nil) 239 snaps.Update(common.HexToHash("0x06"), common.HexToHash("0x05"), nil, e, nil) 240 snaps.Update(common.HexToHash("0x07"), common.HexToHash("0x06"), nil, f, nil) 241 snaps.Update(common.HexToHash("0x08"), common.HexToHash("0x07"), nil, g, nil) 242 snaps.Update(common.HexToHash("0x09"), common.HexToHash("0x08"), nil, h, nil) 243 244 it, _ := snaps.AccountIterator(common.HexToHash("0x09"), common.Hash{}) 245 defer it.Release() 246 247 head := snaps.Snapshot(common.HexToHash("0x09")) 248 for it.Next() { 249 hash := it.Hash() 250 want, err := head.AccountRLP(hash) 251 if err != nil { 252 t.Fatalf("failed to retrieve expected account: %v", err) 253 } 254 if have := it.Account(); !bytes.Equal(want, have) { 255 t.Fatalf("hash %x: account mismatch: have %x, want %x", hash, have, want) 256 } 257 } 258 } 259 260 // This testcase is notorious, all layers contain the exact same 200 accounts. 261 func TestAccountIteratorLargeTraversal(t *testing.T) { 262 // Create a custom account factory to recreate the same addresses 263 makeAccounts := func(num int) map[common.Hash][]byte { 264 accounts := make(map[common.Hash][]byte) 265 for i := 0; i < num; i++ { 266 h := common.Hash{} 267 binary.BigEndian.PutUint64(h[:], uint64(i+1)) 268 accounts[h] = randomAccount() 269 } 270 return accounts 271 } 272 // Build up a large stack of snapshots 273 base := &diskLayer{ 274 diskdb: rawdb.NewMemoryDatabase(), 275 root: common.HexToHash("0x01"), 276 cache: fastcache.New(1024 * 500), 277 } 278 snaps := &Tree{ 279 layers: map[common.Hash]snapshot{ 280 base.root: base, 281 }, 282 } 283 for i := 1; i < 128; i++ { 284 snaps.Update(common.HexToHash(fmt.Sprintf("0x%02x", i+1)), common.HexToHash(fmt.Sprintf("0x%02x", i)), nil, makeAccounts(200), nil) 285 } 286 // Iterate the entire stack and ensure everything is hit only once 287 head := snaps.Snapshot(common.HexToHash("0x80")) 288 verifyIterator(t, 200, head.(snapshot).AccountIterator(common.Hash{})) 289 verifyIterator(t, 200, head.(*diffLayer).newBinaryAccountIterator()) 290 291 it, _ := snaps.AccountIterator(common.HexToHash("0x80"), common.Hash{}) 292 defer it.Release() 293 294 verifyIterator(t, 200, it) 295 } 296 297 // TestAccountIteratorFlattening tests what happens when we 298 // - have a live iterator on child C (parent C1 -> C2 .. CN) 299 // - flattens C2 all the way into CN 300 // - continues iterating 301 func TestAccountIteratorFlattening(t *testing.T) { 302 // Create an empty base layer and a snapshot tree out of it 303 base := &diskLayer{ 304 diskdb: rawdb.NewMemoryDatabase(), 305 root: common.HexToHash("0x01"), 306 cache: fastcache.New(1024 * 500), 307 } 308 snaps := &Tree{ 309 layers: map[common.Hash]snapshot{ 310 base.root: base, 311 }, 312 } 313 // Create a stack of diffs on top 314 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, 315 randomAccountSet("0xaa", "0xee", "0xff", "0xf0"), nil) 316 317 snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, 318 randomAccountSet("0xbb", "0xdd", "0xf0"), nil) 319 320 snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, 321 randomAccountSet("0xcc", "0xf0", "0xff"), nil) 322 323 // Create an iterator and flatten the data from underneath it 324 it, _ := snaps.AccountIterator(common.HexToHash("0x04"), common.Hash{}) 325 defer it.Release() 326 327 if err := snaps.Cap(common.HexToHash("0x04"), 1); err != nil { 328 t.Fatalf("failed to flatten snapshot stack: %v", err) 329 } 330 //verifyIterator(t, 7, it) 331 } 332 333 func TestAccountIteratorSeek(t *testing.T) { 334 // Create a snapshot stack with some initial data 335 base := &diskLayer{ 336 diskdb: rawdb.NewMemoryDatabase(), 337 root: common.HexToHash("0x01"), 338 cache: fastcache.New(1024 * 500), 339 } 340 snaps := &Tree{ 341 layers: map[common.Hash]snapshot{ 342 base.root: base, 343 }, 344 } 345 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, 346 randomAccountSet("0xaa", "0xee", "0xff", "0xf0"), nil) 347 348 snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, 349 randomAccountSet("0xbb", "0xdd", "0xf0"), nil) 350 351 snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, 352 randomAccountSet("0xcc", "0xf0", "0xff"), nil) 353 354 // Construct various iterators and ensure their tranversal is correct 355 it, _ := snaps.AccountIterator(common.HexToHash("0x02"), common.HexToHash("0xdd")) 356 defer it.Release() 357 verifyIterator(t, 3, it) // expected: ee, f0, ff 358 359 it, _ = snaps.AccountIterator(common.HexToHash("0x02"), common.HexToHash("0xaa")) 360 defer it.Release() 361 verifyIterator(t, 3, it) // expected: ee, f0, ff 362 363 it, _ = snaps.AccountIterator(common.HexToHash("0x02"), common.HexToHash("0xff")) 364 defer it.Release() 365 verifyIterator(t, 0, it) // expected: nothing 366 367 it, _ = snaps.AccountIterator(common.HexToHash("0x04"), common.HexToHash("0xbb")) 368 defer it.Release() 369 verifyIterator(t, 5, it) // expected: cc, dd, ee, f0, ff 370 371 it, _ = snaps.AccountIterator(common.HexToHash("0x04"), common.HexToHash("0xef")) 372 defer it.Release() 373 verifyIterator(t, 2, it) // expected: f0, ff 374 375 it, _ = snaps.AccountIterator(common.HexToHash("0x04"), common.HexToHash("0xf0")) 376 defer it.Release() 377 verifyIterator(t, 1, it) // expected: ff 378 379 it, _ = snaps.AccountIterator(common.HexToHash("0x04"), common.HexToHash("0xff")) 380 defer it.Release() 381 verifyIterator(t, 0, it) // expected: nothing 382 } 383 384 // TestIteratorDeletions tests that the iterator behaves correct when there are 385 // deleted accounts (where the Account() value is nil). The iterator 386 // should not output any accounts or nil-values for those cases. 387 func TestIteratorDeletions(t *testing.T) { 388 // Create an empty base layer and a snapshot tree out of it 389 base := &diskLayer{ 390 diskdb: rawdb.NewMemoryDatabase(), 391 root: common.HexToHash("0x01"), 392 cache: fastcache.New(1024 * 500), 393 } 394 snaps := &Tree{ 395 layers: map[common.Hash]snapshot{ 396 base.root: base, 397 }, 398 } 399 // Stack three diff layers on top with various overlaps 400 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), 401 nil, randomAccountSet("0x11", "0x22", "0x33"), nil) 402 403 deleted := common.HexToHash("0x22") 404 destructed := map[common.Hash]struct{}{ 405 deleted: struct{}{}, 406 } 407 snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), 408 destructed, randomAccountSet("0x11", "0x33"), nil) 409 410 snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), 411 nil, randomAccountSet("0x33", "0x44", "0x55"), nil) 412 413 // The output should be 11,33,44,55 414 it, _ := snaps.AccountIterator(common.HexToHash("0x04"), common.Hash{}) 415 // Do a quick check 416 verifyIterator(t, 4, it) 417 it.Release() 418 419 // And a more detailed verification that we indeed do not see '0x22' 420 it, _ = snaps.AccountIterator(common.HexToHash("0x04"), common.Hash{}) 421 defer it.Release() 422 for it.Next() { 423 hash := it.Hash() 424 if it.Account() == nil { 425 t.Errorf("iterator returned nil-value for hash %x", hash) 426 } 427 if hash == deleted { 428 t.Errorf("expected deleted elem %x to not be returned by iterator", deleted) 429 } 430 } 431 } 432 433 // BenchmarkAccountIteratorTraversal is a bit a bit notorious -- all layers contain the 434 // exact same 200 accounts. That means that we need to process 2000 items, but 435 // only spit out 200 values eventually. 436 // 437 // The value-fetching benchmark is easy on the binary iterator, since it never has to reach 438 // down at any depth for retrieving the values -- all are on the toppmost layer 439 // 440 // BenchmarkAccountIteratorTraversal/binary_iterator_keys-6 2239 483674 ns/op 441 // BenchmarkAccountIteratorTraversal/binary_iterator_values-6 2403 501810 ns/op 442 // BenchmarkAccountIteratorTraversal/fast_iterator_keys-6 1923 677966 ns/op 443 // BenchmarkAccountIteratorTraversal/fast_iterator_values-6 1741 649967 ns/op 444 func BenchmarkAccountIteratorTraversal(b *testing.B) { 445 // Create a custom account factory to recreate the same addresses 446 makeAccounts := func(num int) map[common.Hash][]byte { 447 accounts := make(map[common.Hash][]byte) 448 for i := 0; i < num; i++ { 449 h := common.Hash{} 450 binary.BigEndian.PutUint64(h[:], uint64(i+1)) 451 accounts[h] = randomAccount() 452 } 453 return accounts 454 } 455 // Build up a large stack of snapshots 456 base := &diskLayer{ 457 diskdb: rawdb.NewMemoryDatabase(), 458 root: common.HexToHash("0x01"), 459 cache: fastcache.New(1024 * 500), 460 } 461 snaps := &Tree{ 462 layers: map[common.Hash]snapshot{ 463 base.root: base, 464 }, 465 } 466 for i := 1; i <= 100; i++ { 467 snaps.Update(common.HexToHash(fmt.Sprintf("0x%02x", i+1)), common.HexToHash(fmt.Sprintf("0x%02x", i)), nil, makeAccounts(200), nil) 468 } 469 // We call this once before the benchmark, so the creation of 470 // sorted accountlists are not included in the results. 471 head := snaps.Snapshot(common.HexToHash("0x65")) 472 head.(*diffLayer).newBinaryAccountIterator() 473 474 b.Run("binary iterator keys", func(b *testing.B) { 475 for i := 0; i < b.N; i++ { 476 got := 0 477 it := head.(*diffLayer).newBinaryAccountIterator() 478 for it.Next() { 479 got++ 480 } 481 if exp := 200; got != exp { 482 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 483 } 484 } 485 }) 486 b.Run("binary iterator values", func(b *testing.B) { 487 for i := 0; i < b.N; i++ { 488 got := 0 489 it := head.(*diffLayer).newBinaryAccountIterator() 490 for it.Next() { 491 got++ 492 head.(*diffLayer).accountRLP(it.Hash(), 0) 493 } 494 if exp := 200; got != exp { 495 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 496 } 497 } 498 }) 499 b.Run("fast iterator keys", func(b *testing.B) { 500 for i := 0; i < b.N; i++ { 501 it, _ := snaps.AccountIterator(common.HexToHash("0x65"), common.Hash{}) 502 defer it.Release() 503 504 got := 0 505 for it.Next() { 506 got++ 507 } 508 if exp := 200; got != exp { 509 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 510 } 511 } 512 }) 513 b.Run("fast iterator values", func(b *testing.B) { 514 for i := 0; i < b.N; i++ { 515 it, _ := snaps.AccountIterator(common.HexToHash("0x65"), common.Hash{}) 516 defer it.Release() 517 518 got := 0 519 for it.Next() { 520 got++ 521 it.Account() 522 } 523 if exp := 200; got != exp { 524 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 525 } 526 } 527 }) 528 } 529 530 // BenchmarkAccountIteratorLargeBaselayer is a pretty realistic benchmark, where 531 // the baselayer is a lot larger than the upper layer. 532 // 533 // This is heavy on the binary iterator, which in most cases will have to 534 // call recursively 100 times for the majority of the values 535 // 536 // BenchmarkAccountIteratorLargeBaselayer/binary_iterator_(keys)-6 514 1971999 ns/op 537 // BenchmarkAccountIteratorLargeBaselayer/binary_iterator_(values)-6 61 18997492 ns/op 538 // BenchmarkAccountIteratorLargeBaselayer/fast_iterator_(keys)-6 10000 114385 ns/op 539 // BenchmarkAccountIteratorLargeBaselayer/fast_iterator_(values)-6 4047 296823 ns/op 540 func BenchmarkAccountIteratorLargeBaselayer(b *testing.B) { 541 // Create a custom account factory to recreate the same addresses 542 makeAccounts := func(num int) map[common.Hash][]byte { 543 accounts := make(map[common.Hash][]byte) 544 for i := 0; i < num; i++ { 545 h := common.Hash{} 546 binary.BigEndian.PutUint64(h[:], uint64(i+1)) 547 accounts[h] = randomAccount() 548 } 549 return accounts 550 } 551 // Build up a large stack of snapshots 552 base := &diskLayer{ 553 diskdb: rawdb.NewMemoryDatabase(), 554 root: common.HexToHash("0x01"), 555 cache: fastcache.New(1024 * 500), 556 } 557 snaps := &Tree{ 558 layers: map[common.Hash]snapshot{ 559 base.root: base, 560 }, 561 } 562 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, makeAccounts(2000), nil) 563 for i := 2; i <= 100; i++ { 564 snaps.Update(common.HexToHash(fmt.Sprintf("0x%02x", i+1)), common.HexToHash(fmt.Sprintf("0x%02x", i)), nil, makeAccounts(20), nil) 565 } 566 // We call this once before the benchmark, so the creation of 567 // sorted accountlists are not included in the results. 568 head := snaps.Snapshot(common.HexToHash("0x65")) 569 head.(*diffLayer).newBinaryAccountIterator() 570 571 b.Run("binary iterator (keys)", func(b *testing.B) { 572 for i := 0; i < b.N; i++ { 573 got := 0 574 it := head.(*diffLayer).newBinaryAccountIterator() 575 for it.Next() { 576 got++ 577 } 578 if exp := 2000; got != exp { 579 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 580 } 581 } 582 }) 583 b.Run("binary iterator (values)", func(b *testing.B) { 584 for i := 0; i < b.N; i++ { 585 got := 0 586 it := head.(*diffLayer).newBinaryAccountIterator() 587 for it.Next() { 588 got++ 589 v := it.Hash() 590 head.(*diffLayer).accountRLP(v, 0) 591 } 592 if exp := 2000; got != exp { 593 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 594 } 595 } 596 }) 597 b.Run("fast iterator (keys)", func(b *testing.B) { 598 for i := 0; i < b.N; i++ { 599 it, _ := snaps.AccountIterator(common.HexToHash("0x65"), common.Hash{}) 600 defer it.Release() 601 602 got := 0 603 for it.Next() { 604 got++ 605 } 606 if exp := 2000; got != exp { 607 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 608 } 609 } 610 }) 611 b.Run("fast iterator (values)", func(b *testing.B) { 612 for i := 0; i < b.N; i++ { 613 it, _ := snaps.AccountIterator(common.HexToHash("0x65"), common.Hash{}) 614 defer it.Release() 615 616 got := 0 617 for it.Next() { 618 it.Account() 619 got++ 620 } 621 if exp := 2000; got != exp { 622 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 623 } 624 } 625 }) 626 } 627 628 /* 629 func BenchmarkBinaryAccountIteration(b *testing.B) { 630 benchmarkAccountIteration(b, func(snap snapshot) AccountIterator { 631 return snap.(*diffLayer).newBinaryAccountIterator() 632 }) 633 } 634 635 func BenchmarkFastAccountIteration(b *testing.B) { 636 benchmarkAccountIteration(b, newFastAccountIterator) 637 } 638 639 func benchmarkAccountIteration(b *testing.B, iterator func(snap snapshot) AccountIterator) { 640 // Create a diff stack and randomize the accounts across them 641 layers := make([]map[common.Hash][]byte, 128) 642 for i := 0; i < len(layers); i++ { 643 layers[i] = make(map[common.Hash][]byte) 644 } 645 for i := 0; i < b.N; i++ { 646 depth := rand.Intn(len(layers)) 647 layers[depth][randomHash()] = randomAccount() 648 } 649 stack := snapshot(emptyLayer()) 650 for _, layer := range layers { 651 stack = stack.Update(common.Hash{}, layer, nil, nil) 652 } 653 // Reset the timers and report all the stats 654 it := iterator(stack) 655 656 b.ResetTimer() 657 b.ReportAllocs() 658 659 for it.Next() { 660 } 661 } 662 */