github.com/ethereum/go-ethereum@v1.16.1/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 crand "crypto/rand" 22 "encoding/binary" 23 "fmt" 24 "math/rand" 25 "testing" 26 27 "github.com/VictoriaMetrics/fastcache" 28 "github.com/ethereum/go-ethereum/common" 29 "github.com/ethereum/go-ethereum/core/rawdb" 30 ) 31 32 // TestAccountIteratorBasics tests some simple single-layer(diff and disk) iteration 33 func TestAccountIteratorBasics(t *testing.T) { 34 var ( 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(2) == 0 { 45 accStorage := make(map[common.Hash][]byte) 46 value := make([]byte, 32) 47 crand.Read(value) 48 accStorage[randomHash()] = value 49 storage[h] = accStorage 50 } 51 } 52 // Add some (identical) layers on top 53 diffLayer := newDiffLayer(emptyLayer(), common.Hash{}, copyAccounts(accounts), copyStorage(storage)) 54 it := diffLayer.AccountIterator(common.Hash{}) 55 verifyIterator(t, 100, it, verifyNothing) // Nil is allowed for single layer iterator 56 57 it = diffLayer.newBinaryAccountIterator(common.Hash{}) 58 verifyIterator(t, 100, it, verifyNothing) // Nil is allowed for single layer iterator 59 60 diskLayer := diffToDisk(diffLayer) 61 it = diskLayer.AccountIterator(common.Hash{}) 62 verifyIterator(t, 100, it, verifyNothing) // Nil is allowed for single layer iterator 63 } 64 65 // TestStorageIteratorBasics tests some simple single-layer(diff and disk) iteration for storage 66 func TestStorageIteratorBasics(t *testing.T) { 67 var ( 68 nilStorage = make(map[common.Hash]int) 69 accounts = make(map[common.Hash][]byte) 70 storage = make(map[common.Hash]map[common.Hash][]byte) 71 ) 72 // Fill some random data 73 for i := 0; i < 10; i++ { 74 h := randomHash() 75 accounts[h] = randomAccount() 76 77 accStorage := make(map[common.Hash][]byte) 78 value := make([]byte, 32) 79 80 var nilstorage int 81 for i := 0; i < 100; i++ { 82 crand.Read(value) 83 if rand.Intn(2) == 0 { 84 accStorage[randomHash()] = common.CopyBytes(value) 85 } else { 86 accStorage[randomHash()] = nil // delete slot 87 nilstorage += 1 88 } 89 } 90 storage[h] = accStorage 91 nilStorage[h] = nilstorage 92 } 93 // Add some (identical) layers on top 94 diffLayer := newDiffLayer(emptyLayer(), common.Hash{}, copyAccounts(accounts), copyStorage(storage)) 95 for account := range accounts { 96 it := diffLayer.StorageIterator(account, common.Hash{}) 97 verifyIterator(t, 100, it, verifyNothing) // Nil is allowed for single layer iterator 98 } 99 100 diskLayer := diffToDisk(diffLayer) 101 for account := range accounts { 102 it := diskLayer.StorageIterator(account, common.Hash{}) 103 verifyIterator(t, 100-nilStorage[account], it, verifyNothing) // Nil is allowed for single layer iterator 104 } 105 } 106 107 type testIterator struct { 108 values []byte 109 } 110 111 func newTestIterator(values ...byte) *testIterator { 112 return &testIterator{values} 113 } 114 115 func (ti *testIterator) Seek(common.Hash) { 116 panic("implement me") 117 } 118 119 func (ti *testIterator) Next() bool { 120 ti.values = ti.values[1:] 121 return len(ti.values) > 0 122 } 123 124 func (ti *testIterator) Error() error { 125 return nil 126 } 127 128 func (ti *testIterator) Hash() common.Hash { 129 return common.BytesToHash([]byte{ti.values[0]}) 130 } 131 132 func (ti *testIterator) Account() []byte { 133 return nil 134 } 135 136 func (ti *testIterator) Slot() []byte { 137 return nil 138 } 139 140 func (ti *testIterator) Release() {} 141 142 func TestFastIteratorBasics(t *testing.T) { 143 type testCase struct { 144 lists [][]byte 145 expKeys []byte 146 } 147 for i, tc := range []testCase{ 148 {lists: [][]byte{{0, 1, 8}, {1, 2, 8}, {2, 9}, {4}, 149 {7, 14, 15}, {9, 13, 15, 16}}, 150 expKeys: []byte{0, 1, 2, 4, 7, 8, 9, 13, 14, 15, 16}}, 151 {lists: [][]byte{{0, 8}, {1, 2, 8}, {7, 14, 15}, {8, 9}, 152 {9, 10}, {10, 13, 15, 16}}, 153 expKeys: []byte{0, 1, 2, 7, 8, 9, 10, 13, 14, 15, 16}}, 154 } { 155 var iterators []*weightedIterator 156 for i, data := range tc.lists { 157 it := newTestIterator(data...) 158 iterators = append(iterators, &weightedIterator{it, i}) 159 } 160 fi := &fastIterator{ 161 iterators: iterators, 162 initiated: false, 163 } 164 count := 0 165 for fi.Next() { 166 if got, exp := fi.Hash()[31], tc.expKeys[count]; exp != got { 167 t.Errorf("tc %d, [%d]: got %d exp %d", i, count, got, exp) 168 } 169 count++ 170 } 171 } 172 } 173 174 type verifyContent int 175 176 const ( 177 verifyNothing verifyContent = iota 178 verifyAccount 179 verifyStorage 180 ) 181 182 func verifyIterator(t *testing.T, expCount int, it Iterator, verify verifyContent) { 183 t.Helper() 184 185 var ( 186 count = 0 187 last = common.Hash{} 188 ) 189 for it.Next() { 190 hash := it.Hash() 191 if bytes.Compare(last[:], hash[:]) >= 0 { 192 t.Errorf("wrong order: %x >= %x", last, hash) 193 } 194 count++ 195 if verify == verifyAccount && len(it.(AccountIterator).Account()) == 0 { 196 t.Errorf("iterator returned nil-value for hash %x", hash) 197 } else if verify == verifyStorage && len(it.(StorageIterator).Slot()) == 0 { 198 t.Errorf("iterator returned nil-value for hash %x", hash) 199 } 200 last = hash 201 } 202 if count != expCount { 203 t.Errorf("iterator count mismatch: have %d, want %d", count, expCount) 204 } 205 if err := it.Error(); err != nil { 206 t.Errorf("iterator failed: %v", err) 207 } 208 } 209 210 // TestAccountIteratorTraversal tests some simple multi-layer iteration. 211 func TestAccountIteratorTraversal(t *testing.T) { 212 // Create an empty base layer and a snapshot tree out of it 213 base := &diskLayer{ 214 diskdb: rawdb.NewMemoryDatabase(), 215 root: common.HexToHash("0x01"), 216 cache: fastcache.New(1024 * 500), 217 } 218 snaps := &Tree{ 219 layers: map[common.Hash]snapshot{ 220 base.root: base, 221 }, 222 } 223 // Stack three diff layers on top with various overlaps 224 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), 225 randomAccountSet("0xaa", "0xee", "0xff", "0xf0"), nil) 226 227 snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), 228 randomAccountSet("0xbb", "0xdd", "0xf0"), nil) 229 230 snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), 231 randomAccountSet("0xcc", "0xf0", "0xff"), nil) 232 233 // Verify the single and multi-layer iterators 234 head := snaps.Snapshot(common.HexToHash("0x04")) 235 236 verifyIterator(t, 3, head.(snapshot).AccountIterator(common.Hash{}), verifyNothing) 237 verifyIterator(t, 7, head.(*diffLayer).newBinaryAccountIterator(common.Hash{}), verifyAccount) 238 239 it, _ := snaps.AccountIterator(common.HexToHash("0x04"), common.Hash{}) 240 verifyIterator(t, 7, it, verifyAccount) 241 it.Release() 242 243 // Test after persist some bottom-most layers into the disk, 244 // the functionalities still work. 245 limit := aggregatorMemoryLimit 246 defer func() { 247 aggregatorMemoryLimit = limit 248 }() 249 aggregatorMemoryLimit = 0 // Force pushing the bottom-most layer into disk 250 snaps.Cap(common.HexToHash("0x04"), 2) 251 verifyIterator(t, 7, head.(*diffLayer).newBinaryAccountIterator(common.Hash{}), verifyAccount) 252 253 it, _ = snaps.AccountIterator(common.HexToHash("0x04"), common.Hash{}) 254 verifyIterator(t, 7, it, verifyAccount) 255 it.Release() 256 } 257 258 func TestStorageIteratorTraversal(t *testing.T) { 259 // Create an empty base layer and a snapshot tree out of it 260 base := &diskLayer{ 261 diskdb: rawdb.NewMemoryDatabase(), 262 root: common.HexToHash("0x01"), 263 cache: fastcache.New(1024 * 500), 264 } 265 snaps := &Tree{ 266 layers: map[common.Hash]snapshot{ 267 base.root: base, 268 }, 269 } 270 // Stack three diff layers on top with various overlaps 271 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), 272 randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x02", "0x03"}}, nil)) 273 274 snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), 275 randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x04", "0x05", "0x06"}}, nil)) 276 277 snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), 278 randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x02", "0x03"}}, nil)) 279 280 // Verify the single and multi-layer iterators 281 head := snaps.Snapshot(common.HexToHash("0x04")) 282 283 diffIter := head.(snapshot).StorageIterator(common.HexToHash("0xaa"), common.Hash{}) 284 verifyIterator(t, 3, diffIter, verifyNothing) 285 verifyIterator(t, 6, head.(*diffLayer).newBinaryStorageIterator(common.HexToHash("0xaa"), common.Hash{}), verifyStorage) 286 287 it, _ := snaps.StorageIterator(common.HexToHash("0x04"), common.HexToHash("0xaa"), common.Hash{}) 288 verifyIterator(t, 6, it, verifyStorage) 289 it.Release() 290 291 // Test after persist some bottom-most layers into the disk, 292 // the functionalities still work. 293 limit := aggregatorMemoryLimit 294 defer func() { 295 aggregatorMemoryLimit = limit 296 }() 297 aggregatorMemoryLimit = 0 // Force pushing the bottom-most layer into disk 298 snaps.Cap(common.HexToHash("0x04"), 2) 299 verifyIterator(t, 6, head.(*diffLayer).newBinaryStorageIterator(common.HexToHash("0xaa"), common.Hash{}), verifyStorage) 300 301 it, _ = snaps.StorageIterator(common.HexToHash("0x04"), common.HexToHash("0xaa"), common.Hash{}) 302 verifyIterator(t, 6, it, verifyStorage) 303 it.Release() 304 } 305 306 // TestAccountIteratorTraversalValues tests some multi-layer iteration, where we 307 // also expect the correct values to show up. 308 func TestAccountIteratorTraversalValues(t *testing.T) { 309 // Create an empty base layer and a snapshot tree out of it 310 base := &diskLayer{ 311 diskdb: rawdb.NewMemoryDatabase(), 312 root: common.HexToHash("0x01"), 313 cache: fastcache.New(1024 * 500), 314 } 315 snaps := &Tree{ 316 layers: map[common.Hash]snapshot{ 317 base.root: base, 318 }, 319 } 320 // Create a batch of account sets to seed subsequent layers with 321 var ( 322 a = make(map[common.Hash][]byte) 323 b = make(map[common.Hash][]byte) 324 c = make(map[common.Hash][]byte) 325 d = make(map[common.Hash][]byte) 326 e = make(map[common.Hash][]byte) 327 f = make(map[common.Hash][]byte) 328 g = make(map[common.Hash][]byte) 329 h = make(map[common.Hash][]byte) 330 ) 331 for i := byte(2); i < 0xff; i++ { 332 a[common.Hash{i}] = fmt.Appendf(nil, "layer-%d, key %d", 0, i) 333 if i > 20 && i%2 == 0 { 334 b[common.Hash{i}] = fmt.Appendf(nil, "layer-%d, key %d", 1, i) 335 } 336 if i%4 == 0 { 337 c[common.Hash{i}] = fmt.Appendf(nil, "layer-%d, key %d", 2, i) 338 } 339 if i%7 == 0 { 340 d[common.Hash{i}] = fmt.Appendf(nil, "layer-%d, key %d", 3, i) 341 } 342 if i%8 == 0 { 343 e[common.Hash{i}] = fmt.Appendf(nil, "layer-%d, key %d", 4, i) 344 } 345 if i > 50 || i < 85 { 346 f[common.Hash{i}] = fmt.Appendf(nil, "layer-%d, key %d", 5, i) 347 } 348 if i%64 == 0 { 349 g[common.Hash{i}] = fmt.Appendf(nil, "layer-%d, key %d", 6, i) 350 } 351 if i%128 == 0 { 352 h[common.Hash{i}] = fmt.Appendf(nil, "layer-%d, key %d", 7, i) 353 } 354 } 355 // Assemble a stack of snapshots from the account layers 356 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), a, nil) 357 snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), b, nil) 358 snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), c, nil) 359 snaps.Update(common.HexToHash("0x05"), common.HexToHash("0x04"), d, nil) 360 snaps.Update(common.HexToHash("0x06"), common.HexToHash("0x05"), e, nil) 361 snaps.Update(common.HexToHash("0x07"), common.HexToHash("0x06"), f, nil) 362 snaps.Update(common.HexToHash("0x08"), common.HexToHash("0x07"), g, nil) 363 snaps.Update(common.HexToHash("0x09"), common.HexToHash("0x08"), h, nil) 364 365 it, _ := snaps.AccountIterator(common.HexToHash("0x09"), common.Hash{}) 366 head := snaps.Snapshot(common.HexToHash("0x09")) 367 for it.Next() { 368 hash := it.Hash() 369 want, err := head.AccountRLP(hash) 370 if err != nil { 371 t.Fatalf("failed to retrieve expected account: %v", err) 372 } 373 if have := it.Account(); !bytes.Equal(want, have) { 374 t.Fatalf("hash %x: account mismatch: have %x, want %x", hash, have, want) 375 } 376 } 377 it.Release() 378 379 // Test after persist some bottom-most layers into the disk, 380 // the functionalities still work. 381 limit := aggregatorMemoryLimit 382 defer func() { 383 aggregatorMemoryLimit = limit 384 }() 385 aggregatorMemoryLimit = 0 // Force pushing the bottom-most layer into disk 386 snaps.Cap(common.HexToHash("0x09"), 2) 387 388 it, _ = snaps.AccountIterator(common.HexToHash("0x09"), common.Hash{}) 389 for it.Next() { 390 hash := it.Hash() 391 want, err := head.AccountRLP(hash) 392 if err != nil { 393 t.Fatalf("failed to retrieve expected account: %v", err) 394 } 395 if have := it.Account(); !bytes.Equal(want, have) { 396 t.Fatalf("hash %x: account mismatch: have %x, want %x", hash, have, want) 397 } 398 } 399 it.Release() 400 } 401 402 func TestStorageIteratorTraversalValues(t *testing.T) { 403 // Create an empty base layer and a snapshot tree out of it 404 base := &diskLayer{ 405 diskdb: rawdb.NewMemoryDatabase(), 406 root: common.HexToHash("0x01"), 407 cache: fastcache.New(1024 * 500), 408 } 409 snaps := &Tree{ 410 layers: map[common.Hash]snapshot{ 411 base.root: base, 412 }, 413 } 414 wrapStorage := func(storage map[common.Hash][]byte) map[common.Hash]map[common.Hash][]byte { 415 return map[common.Hash]map[common.Hash][]byte{ 416 common.HexToHash("0xaa"): storage, 417 } 418 } 419 // Create a batch of storage sets to seed subsequent layers with 420 var ( 421 a = make(map[common.Hash][]byte) 422 b = make(map[common.Hash][]byte) 423 c = make(map[common.Hash][]byte) 424 d = make(map[common.Hash][]byte) 425 e = make(map[common.Hash][]byte) 426 f = make(map[common.Hash][]byte) 427 g = make(map[common.Hash][]byte) 428 h = make(map[common.Hash][]byte) 429 ) 430 for i := byte(2); i < 0xff; i++ { 431 a[common.Hash{i}] = fmt.Appendf(nil, "layer-%d, key %d", 0, i) 432 if i > 20 && i%2 == 0 { 433 b[common.Hash{i}] = fmt.Appendf(nil, "layer-%d, key %d", 1, i) 434 } 435 if i%4 == 0 { 436 c[common.Hash{i}] = fmt.Appendf(nil, "layer-%d, key %d", 2, i) 437 } 438 if i%7 == 0 { 439 d[common.Hash{i}] = fmt.Appendf(nil, "layer-%d, key %d", 3, i) 440 } 441 if i%8 == 0 { 442 e[common.Hash{i}] = fmt.Appendf(nil, "layer-%d, key %d", 4, i) 443 } 444 if i > 50 || i < 85 { 445 f[common.Hash{i}] = fmt.Appendf(nil, "layer-%d, key %d", 5, i) 446 } 447 if i%64 == 0 { 448 g[common.Hash{i}] = fmt.Appendf(nil, "layer-%d, key %d", 6, i) 449 } 450 if i%128 == 0 { 451 h[common.Hash{i}] = fmt.Appendf(nil, "layer-%d, key %d", 7, i) 452 } 453 } 454 // Assemble a stack of snapshots from the account layers 455 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), randomAccountSet("0xaa"), wrapStorage(a)) 456 snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), randomAccountSet("0xaa"), wrapStorage(b)) 457 snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), randomAccountSet("0xaa"), wrapStorage(c)) 458 snaps.Update(common.HexToHash("0x05"), common.HexToHash("0x04"), randomAccountSet("0xaa"), wrapStorage(d)) 459 snaps.Update(common.HexToHash("0x06"), common.HexToHash("0x05"), randomAccountSet("0xaa"), wrapStorage(e)) 460 snaps.Update(common.HexToHash("0x07"), common.HexToHash("0x06"), randomAccountSet("0xaa"), wrapStorage(e)) 461 snaps.Update(common.HexToHash("0x08"), common.HexToHash("0x07"), randomAccountSet("0xaa"), wrapStorage(g)) 462 snaps.Update(common.HexToHash("0x09"), common.HexToHash("0x08"), randomAccountSet("0xaa"), wrapStorage(h)) 463 464 it, _ := snaps.StorageIterator(common.HexToHash("0x09"), common.HexToHash("0xaa"), common.Hash{}) 465 head := snaps.Snapshot(common.HexToHash("0x09")) 466 for it.Next() { 467 hash := it.Hash() 468 want, err := head.Storage(common.HexToHash("0xaa"), hash) 469 if err != nil { 470 t.Fatalf("failed to retrieve expected storage slot: %v", err) 471 } 472 if have := it.Slot(); !bytes.Equal(want, have) { 473 t.Fatalf("hash %x: slot mismatch: have %x, want %x", hash, have, want) 474 } 475 } 476 it.Release() 477 478 // Test after persist some bottom-most layers into the disk, 479 // the functionalities still work. 480 limit := aggregatorMemoryLimit 481 defer func() { 482 aggregatorMemoryLimit = limit 483 }() 484 aggregatorMemoryLimit = 0 // Force pushing the bottom-most layer into disk 485 snaps.Cap(common.HexToHash("0x09"), 2) 486 487 it, _ = snaps.StorageIterator(common.HexToHash("0x09"), common.HexToHash("0xaa"), common.Hash{}) 488 for it.Next() { 489 hash := it.Hash() 490 want, err := head.Storage(common.HexToHash("0xaa"), hash) 491 if err != nil { 492 t.Fatalf("failed to retrieve expected slot: %v", err) 493 } 494 if have := it.Slot(); !bytes.Equal(want, have) { 495 t.Fatalf("hash %x: slot mismatch: have %x, want %x", hash, have, want) 496 } 497 } 498 it.Release() 499 } 500 501 // This testcase is notorious, all layers contain the exact same 200 accounts. 502 func TestAccountIteratorLargeTraversal(t *testing.T) { 503 // Create a custom account factory to recreate the same addresses 504 makeAccounts := func(num int) map[common.Hash][]byte { 505 accounts := make(map[common.Hash][]byte) 506 for i := 0; i < num; i++ { 507 h := common.Hash{} 508 binary.BigEndian.PutUint64(h[:], uint64(i+1)) 509 accounts[h] = randomAccount() 510 } 511 return accounts 512 } 513 // Build up a large stack of snapshots 514 base := &diskLayer{ 515 diskdb: rawdb.NewMemoryDatabase(), 516 root: common.HexToHash("0x01"), 517 cache: fastcache.New(1024 * 500), 518 } 519 snaps := &Tree{ 520 layers: map[common.Hash]snapshot{ 521 base.root: base, 522 }, 523 } 524 for i := 1; i < 128; i++ { 525 snaps.Update(common.HexToHash(fmt.Sprintf("0x%02x", i+1)), common.HexToHash(fmt.Sprintf("0x%02x", i)), makeAccounts(200), nil) 526 } 527 // Iterate the entire stack and ensure everything is hit only once 528 head := snaps.Snapshot(common.HexToHash("0x80")) 529 verifyIterator(t, 200, head.(snapshot).AccountIterator(common.Hash{}), verifyNothing) 530 verifyIterator(t, 200, head.(*diffLayer).newBinaryAccountIterator(common.Hash{}), verifyAccount) 531 532 it, _ := snaps.AccountIterator(common.HexToHash("0x80"), common.Hash{}) 533 verifyIterator(t, 200, it, verifyAccount) 534 it.Release() 535 536 // Test after persist some bottom-most layers into the disk, 537 // the functionalities still work. 538 limit := aggregatorMemoryLimit 539 defer func() { 540 aggregatorMemoryLimit = limit 541 }() 542 aggregatorMemoryLimit = 0 // Force pushing the bottom-most layer into disk 543 snaps.Cap(common.HexToHash("0x80"), 2) 544 545 verifyIterator(t, 200, head.(*diffLayer).newBinaryAccountIterator(common.Hash{}), verifyAccount) 546 547 it, _ = snaps.AccountIterator(common.HexToHash("0x80"), common.Hash{}) 548 verifyIterator(t, 200, it, verifyAccount) 549 it.Release() 550 } 551 552 // TestAccountIteratorFlattening tests what happens when we 553 // - have a live iterator on child C (parent C1 -> C2 .. CN) 554 // - flattens C2 all the way into CN 555 // - continues iterating 556 func TestAccountIteratorFlattening(t *testing.T) { 557 t.Run("fast", func(t *testing.T) { 558 testAccountIteratorFlattening(t, func(snaps *Tree, root, seek common.Hash) AccountIterator { 559 it, _ := snaps.AccountIterator(root, seek) 560 return it 561 }) 562 }) 563 t.Run("binary", func(t *testing.T) { 564 testAccountIteratorFlattening(t, func(snaps *Tree, root, seek common.Hash) AccountIterator { 565 return snaps.layers[root].(*diffLayer).newBinaryAccountIterator(seek) 566 }) 567 }) 568 } 569 570 func testAccountIteratorFlattening(t *testing.T, newIterator func(snaps *Tree, root, seek common.Hash) AccountIterator) { 571 // Create an empty base layer and a snapshot tree out of it 572 base := &diskLayer{ 573 diskdb: rawdb.NewMemoryDatabase(), 574 root: common.HexToHash("0x01"), 575 cache: fastcache.New(1024 * 500), 576 } 577 snaps := &Tree{ 578 layers: map[common.Hash]snapshot{ 579 base.root: base, 580 }, 581 } 582 // Create a stack of diffs on top 583 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), 584 randomAccountSet("0xaa", "0xee", "0xff", "0xf0"), nil) 585 586 snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), 587 randomAccountSet("0xbb", "0xdd", "0xf0"), nil) 588 589 snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), 590 randomAccountSet("0xcc", "0xf0", "0xff"), nil) 591 592 // Create an iterator and flatten the data from underneath it 593 it := newIterator(snaps, common.HexToHash("0x04"), common.Hash{}) 594 defer it.Release() 595 596 if err := snaps.Cap(common.HexToHash("0x04"), 1); err != nil { 597 t.Fatalf("failed to flatten snapshot stack: %v", err) 598 } 599 //verifyIterator(t, 7, it) 600 } 601 602 func TestAccountIteratorSeek(t *testing.T) { 603 t.Run("fast", func(t *testing.T) { 604 testAccountIteratorSeek(t, func(snaps *Tree, root, seek common.Hash) AccountIterator { 605 it, _ := snaps.AccountIterator(root, seek) 606 return it 607 }) 608 }) 609 t.Run("binary", func(t *testing.T) { 610 testAccountIteratorSeek(t, func(snaps *Tree, root, seek common.Hash) AccountIterator { 611 it := snaps.layers[root].(*diffLayer).newBinaryAccountIterator(seek) 612 return it 613 }) 614 }) 615 } 616 617 func testAccountIteratorSeek(t *testing.T, newIterator func(snaps *Tree, root, seek common.Hash) AccountIterator) { 618 // Create a snapshot stack with some initial data 619 base := &diskLayer{ 620 diskdb: rawdb.NewMemoryDatabase(), 621 root: common.HexToHash("0x01"), 622 cache: fastcache.New(1024 * 500), 623 } 624 snaps := &Tree{ 625 layers: map[common.Hash]snapshot{ 626 base.root: base, 627 }, 628 } 629 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), 630 randomAccountSet("0xaa", "0xee", "0xff", "0xf0"), nil) 631 632 snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), 633 randomAccountSet("0xbb", "0xdd", "0xf0"), nil) 634 635 snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), 636 randomAccountSet("0xcc", "0xf0", "0xff"), nil) 637 638 // Account set is now 639 // 02: aa, ee, f0, ff 640 // 03: aa, bb, dd, ee, f0 (, f0), ff 641 // 04: aa, bb, cc, dd, ee, f0 (, f0), ff (, ff) 642 // Construct various iterators and ensure their traversal is correct 643 it := newIterator(snaps, common.HexToHash("0x02"), common.HexToHash("0xdd")) 644 defer it.Release() 645 verifyIterator(t, 3, it, verifyAccount) // expected: ee, f0, ff 646 647 it = newIterator(snaps, common.HexToHash("0x02"), common.HexToHash("0xaa")) 648 defer it.Release() 649 verifyIterator(t, 4, it, verifyAccount) // expected: aa, ee, f0, ff 650 651 it = newIterator(snaps, common.HexToHash("0x02"), common.HexToHash("0xff")) 652 defer it.Release() 653 verifyIterator(t, 1, it, verifyAccount) // expected: ff 654 655 it = newIterator(snaps, common.HexToHash("0x02"), common.HexToHash("0xff1")) 656 defer it.Release() 657 verifyIterator(t, 0, it, verifyAccount) // expected: nothing 658 659 it = newIterator(snaps, common.HexToHash("0x04"), common.HexToHash("0xbb")) 660 defer it.Release() 661 verifyIterator(t, 6, it, verifyAccount) // expected: bb, cc, dd, ee, f0, ff 662 663 it = newIterator(snaps, common.HexToHash("0x04"), common.HexToHash("0xef")) 664 defer it.Release() 665 verifyIterator(t, 2, it, verifyAccount) // expected: f0, ff 666 667 it = newIterator(snaps, common.HexToHash("0x04"), common.HexToHash("0xf0")) 668 defer it.Release() 669 verifyIterator(t, 2, it, verifyAccount) // expected: f0, ff 670 671 it = newIterator(snaps, common.HexToHash("0x04"), common.HexToHash("0xff")) 672 defer it.Release() 673 verifyIterator(t, 1, it, verifyAccount) // expected: ff 674 675 it = newIterator(snaps, common.HexToHash("0x04"), common.HexToHash("0xff1")) 676 defer it.Release() 677 verifyIterator(t, 0, it, verifyAccount) // expected: nothing 678 } 679 680 func TestStorageIteratorSeek(t *testing.T) { 681 t.Run("fast", func(t *testing.T) { 682 testStorageIteratorSeek(t, func(snaps *Tree, root, account, seek common.Hash) StorageIterator { 683 it, _ := snaps.StorageIterator(root, account, seek) 684 return it 685 }) 686 }) 687 t.Run("binary", func(t *testing.T) { 688 testStorageIteratorSeek(t, func(snaps *Tree, root, account, seek common.Hash) StorageIterator { 689 return snaps.layers[root].(*diffLayer).newBinaryStorageIterator(account, seek) 690 }) 691 }) 692 } 693 694 func testStorageIteratorSeek(t *testing.T, newIterator func(snaps *Tree, root, account, seek common.Hash) StorageIterator) { 695 // Create a snapshot stack with some initial data 696 base := &diskLayer{ 697 diskdb: rawdb.NewMemoryDatabase(), 698 root: common.HexToHash("0x01"), 699 cache: fastcache.New(1024 * 500), 700 } 701 snaps := &Tree{ 702 layers: map[common.Hash]snapshot{ 703 base.root: base, 704 }, 705 } 706 // Stack three diff layers on top with various overlaps 707 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), 708 randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x03", "0x05"}}, nil)) 709 710 snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), 711 randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x02", "0x05", "0x06"}}, nil)) 712 713 snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), 714 randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x05", "0x08"}}, nil)) 715 716 // Account set is now 717 // 02: 01, 03, 05 718 // 03: 01, 02, 03, 05 (, 05), 06 719 // 04: 01(, 01), 02, 03, 05(, 05, 05), 06, 08 720 // Construct various iterators and ensure their traversal is correct 721 it := newIterator(snaps, common.HexToHash("0x02"), common.HexToHash("0xaa"), common.HexToHash("0x01")) 722 defer it.Release() 723 verifyIterator(t, 3, it, verifyStorage) // expected: 01, 03, 05 724 725 it = newIterator(snaps, common.HexToHash("0x02"), common.HexToHash("0xaa"), common.HexToHash("0x02")) 726 defer it.Release() 727 verifyIterator(t, 2, it, verifyStorage) // expected: 03, 05 728 729 it = newIterator(snaps, common.HexToHash("0x02"), common.HexToHash("0xaa"), common.HexToHash("0x5")) 730 defer it.Release() 731 verifyIterator(t, 1, it, verifyStorage) // expected: 05 732 733 it = newIterator(snaps, common.HexToHash("0x02"), common.HexToHash("0xaa"), common.HexToHash("0x6")) 734 defer it.Release() 735 verifyIterator(t, 0, it, verifyStorage) // expected: nothing 736 737 it = newIterator(snaps, common.HexToHash("0x04"), common.HexToHash("0xaa"), common.HexToHash("0x01")) 738 defer it.Release() 739 verifyIterator(t, 6, it, verifyStorage) // expected: 01, 02, 03, 05, 06, 08 740 741 it = newIterator(snaps, common.HexToHash("0x04"), common.HexToHash("0xaa"), common.HexToHash("0x05")) 742 defer it.Release() 743 verifyIterator(t, 3, it, verifyStorage) // expected: 05, 06, 08 744 745 it = newIterator(snaps, common.HexToHash("0x04"), common.HexToHash("0xaa"), common.HexToHash("0x08")) 746 defer it.Release() 747 verifyIterator(t, 1, it, verifyStorage) // expected: 08 748 749 it = newIterator(snaps, common.HexToHash("0x04"), common.HexToHash("0xaa"), common.HexToHash("0x09")) 750 defer it.Release() 751 verifyIterator(t, 0, it, verifyStorage) // expected: nothing 752 } 753 754 // TestAccountIteratorDeletions tests that the iterator behaves correct when there are 755 // deleted accounts (where the Account() value is nil). The iterator 756 // should not output any accounts or nil-values for those cases. 757 func TestAccountIteratorDeletions(t *testing.T) { 758 t.Run("fast", func(t *testing.T) { 759 testAccountIteratorDeletions(t, func(snaps *Tree, root, seek common.Hash) AccountIterator { 760 it, _ := snaps.AccountIterator(root, seek) 761 return it 762 }) 763 }) 764 t.Run("binary", func(t *testing.T) { 765 testAccountIteratorDeletions(t, func(snaps *Tree, root, seek common.Hash) AccountIterator { 766 return snaps.layers[root].(*diffLayer).newBinaryAccountIterator(seek) 767 }) 768 }) 769 } 770 771 func testAccountIteratorDeletions(t *testing.T, newIterator func(snaps *Tree, root, seek common.Hash) AccountIterator) { 772 // Create an empty base layer and a snapshot tree out of it 773 base := &diskLayer{ 774 diskdb: rawdb.NewMemoryDatabase(), 775 root: common.HexToHash("0x01"), 776 cache: fastcache.New(1024 * 500), 777 } 778 snaps := &Tree{ 779 layers: map[common.Hash]snapshot{ 780 base.root: base, 781 }, 782 } 783 // Stack three diff layers on top with various overlaps 784 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), randomAccountSet("0x11", "0x22", "0x33"), nil) 785 786 set := randomAccountSet("0x11", "0x33") 787 set[common.HexToHash("0x22")] = nil 788 snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), set, nil) 789 snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), 790 randomAccountSet("0x33", "0x44", "0x55"), nil) 791 792 // The output should be 11,33,44,55 793 it := newIterator(snaps, common.HexToHash("0x04"), common.Hash{}) 794 795 // Do a quick check 796 verifyIterator(t, 4, it, verifyAccount) 797 it.Release() 798 799 // And a more detailed verification that we indeed do not see '0x22' 800 it, _ = snaps.AccountIterator(common.HexToHash("0x04"), common.Hash{}) 801 defer it.Release() 802 for it.Next() { 803 hash := it.Hash() 804 if it.Account() == nil { 805 t.Errorf("iterator returned nil-value for hash %x", hash) 806 } 807 if hash == common.HexToHash("0x22") { 808 t.Errorf("expected deleted elem %x to not be returned by iterator", common.HexToHash("0x22")) 809 } 810 } 811 } 812 813 func TestStorageIteratorDeletions(t *testing.T) { 814 t.Run("fast", func(t *testing.T) { 815 testStorageIteratorDeletions(t, func(snaps *Tree, root, account, seek common.Hash) StorageIterator { 816 it, _ := snaps.StorageIterator(root, account, seek) 817 return it 818 }) 819 }) 820 t.Run("binary", func(t *testing.T) { 821 testStorageIteratorDeletions(t, func(snaps *Tree, root, account, seek common.Hash) StorageIterator { 822 return snaps.layers[root].(*diffLayer).newBinaryStorageIterator(account, seek) 823 }) 824 }) 825 } 826 827 func testStorageIteratorDeletions(t *testing.T, newIterator func(snaps *Tree, root, account, seek common.Hash) StorageIterator) { 828 // Create an empty base layer and a snapshot tree out of it 829 base := &diskLayer{ 830 diskdb: rawdb.NewMemoryDatabase(), 831 root: common.HexToHash("0x01"), 832 cache: fastcache.New(1024 * 500), 833 } 834 snaps := &Tree{ 835 layers: map[common.Hash]snapshot{ 836 base.root: base, 837 }, 838 } 839 // Stack three diff layers on top with various overlaps 840 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), 841 randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x03", "0x05"}}, nil)) 842 843 snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), 844 randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x02", "0x04", "0x06"}}, [][]string{{"0x01", "0x03"}})) 845 846 // The output should be 02,04,05,06 847 it := newIterator(snaps, common.HexToHash("0x03"), common.HexToHash("0xaa"), common.Hash{}) 848 verifyIterator(t, 4, it, verifyStorage) 849 it.Release() 850 851 // The output should be 04,05,06 852 it = newIterator(snaps, common.HexToHash("0x03"), common.HexToHash("0xaa"), common.HexToHash("0x03")) 853 verifyIterator(t, 3, it, verifyStorage) 854 it.Release() 855 856 // Destruct the whole storage 857 snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), 858 map[common.Hash][]byte{common.HexToHash("0xaa"): nil}, 859 randomStorageSet([]string{"0xaa"}, nil, [][]string{{"0x02", "0x04", "0x05", "0x06"}})) 860 861 it = newIterator(snaps, common.HexToHash("0x04"), common.HexToHash("0xaa"), common.Hash{}) 862 verifyIterator(t, 0, it, verifyStorage) 863 it.Release() 864 865 // Re-insert the slots of the same account 866 snaps.Update(common.HexToHash("0x05"), common.HexToHash("0x04"), 867 randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x07", "0x08", "0x09"}}, nil)) 868 869 // The output should be 07,08,09 870 871 it = newIterator(snaps, common.HexToHash("0x05"), common.HexToHash("0xaa"), common.Hash{}) 872 verifyIterator(t, 3, it, verifyStorage) 873 it.Release() 874 875 // Destruct the whole storage but re-create the account in the same layer 876 snaps.Update(common.HexToHash("0x06"), common.HexToHash("0x05"), 877 randomAccountSet("0xaa"), 878 randomStorageSet([]string{"0xaa"}, [][]string{{"0x11", "0x12"}}, [][]string{{"0x07", "0x08", "0x09"}})) 879 it = newIterator(snaps, common.HexToHash("0x06"), common.HexToHash("0xaa"), common.Hash{}) 880 verifyIterator(t, 2, it, verifyStorage) // The output should be 11,12 881 it.Release() 882 883 verifyIterator(t, 2, snaps.Snapshot( 884 common.HexToHash("0x06")).(*diffLayer). 885 newBinaryStorageIterator(common.HexToHash("0xaa"), common.Hash{}), 886 verifyStorage) 887 } 888 889 // BenchmarkAccountIteratorTraversal is a bit notorious -- all layers contain the 890 // exact same 200 accounts. That means that we need to process 2000 items, but 891 // only spit out 200 values eventually. 892 // 893 // The value-fetching benchmark is easy on the binary iterator, since it never has to reach 894 // down at any depth for retrieving the values -- all are on the topmost layer 895 // 896 // BenchmarkAccountIteratorTraversal/binary_iterator_keys-6 2239 483674 ns/op 897 // BenchmarkAccountIteratorTraversal/binary_iterator_values-6 2403 501810 ns/op 898 // BenchmarkAccountIteratorTraversal/fast_iterator_keys-6 1923 677966 ns/op 899 // BenchmarkAccountIteratorTraversal/fast_iterator_values-6 1741 649967 ns/op 900 func BenchmarkAccountIteratorTraversal(b *testing.B) { 901 // Create a custom account factory to recreate the same addresses 902 makeAccounts := func(num int) map[common.Hash][]byte { 903 accounts := make(map[common.Hash][]byte) 904 for i := 0; i < num; i++ { 905 h := common.Hash{} 906 binary.BigEndian.PutUint64(h[:], uint64(i+1)) 907 accounts[h] = randomAccount() 908 } 909 return accounts 910 } 911 // Build up a large stack of snapshots 912 base := &diskLayer{ 913 diskdb: rawdb.NewMemoryDatabase(), 914 root: common.HexToHash("0x01"), 915 cache: fastcache.New(1024 * 500), 916 } 917 snaps := &Tree{ 918 layers: map[common.Hash]snapshot{ 919 base.root: base, 920 }, 921 } 922 for i := 1; i <= 100; i++ { 923 snaps.Update(common.HexToHash(fmt.Sprintf("0x%02x", i+1)), common.HexToHash(fmt.Sprintf("0x%02x", i)), makeAccounts(200), nil) 924 } 925 // We call this once before the benchmark, so the creation of 926 // sorted accountlists are not included in the results. 927 head := snaps.Snapshot(common.HexToHash("0x65")) 928 head.(*diffLayer).newBinaryAccountIterator(common.Hash{}) 929 930 b.Run("binary iterator keys", func(b *testing.B) { 931 for i := 0; i < b.N; i++ { 932 got := 0 933 it := head.(*diffLayer).newBinaryAccountIterator(common.Hash{}) 934 for it.Next() { 935 got++ 936 } 937 if exp := 200; got != exp { 938 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 939 } 940 } 941 }) 942 b.Run("binary iterator values", func(b *testing.B) { 943 for i := 0; i < b.N; i++ { 944 got := 0 945 it := head.(*diffLayer).newBinaryAccountIterator(common.Hash{}) 946 for it.Next() { 947 got++ 948 head.(*diffLayer).accountRLP(it.Hash(), 0) 949 } 950 if exp := 200; got != exp { 951 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 952 } 953 } 954 }) 955 b.Run("fast iterator keys", func(b *testing.B) { 956 for i := 0; i < b.N; i++ { 957 it, _ := snaps.AccountIterator(common.HexToHash("0x65"), common.Hash{}) 958 defer it.Release() 959 960 got := 0 961 for it.Next() { 962 got++ 963 } 964 if exp := 200; got != exp { 965 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 966 } 967 } 968 }) 969 b.Run("fast iterator values", func(b *testing.B) { 970 for i := 0; i < b.N; i++ { 971 it, _ := snaps.AccountIterator(common.HexToHash("0x65"), common.Hash{}) 972 defer it.Release() 973 974 got := 0 975 for it.Next() { 976 got++ 977 it.Account() 978 } 979 if exp := 200; got != exp { 980 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 981 } 982 } 983 }) 984 } 985 986 // BenchmarkAccountIteratorLargeBaselayer is a pretty realistic benchmark, where 987 // the baselayer is a lot larger than the upper layer. 988 // 989 // This is heavy on the binary iterator, which in most cases will have to 990 // call recursively 100 times for the majority of the values 991 // 992 // BenchmarkAccountIteratorLargeBaselayer/binary_iterator_(keys)-6 514 1971999 ns/op 993 // BenchmarkAccountIteratorLargeBaselayer/binary_iterator_(values)-6 61 18997492 ns/op 994 // BenchmarkAccountIteratorLargeBaselayer/fast_iterator_(keys)-6 10000 114385 ns/op 995 // BenchmarkAccountIteratorLargeBaselayer/fast_iterator_(values)-6 4047 296823 ns/op 996 func BenchmarkAccountIteratorLargeBaselayer(b *testing.B) { 997 // Create a custom account factory to recreate the same addresses 998 makeAccounts := func(num int) map[common.Hash][]byte { 999 accounts := make(map[common.Hash][]byte) 1000 for i := 0; i < num; i++ { 1001 h := common.Hash{} 1002 binary.BigEndian.PutUint64(h[:], uint64(i+1)) 1003 accounts[h] = randomAccount() 1004 } 1005 return accounts 1006 } 1007 // Build up a large stack of snapshots 1008 base := &diskLayer{ 1009 diskdb: rawdb.NewMemoryDatabase(), 1010 root: common.HexToHash("0x01"), 1011 cache: fastcache.New(1024 * 500), 1012 } 1013 snaps := &Tree{ 1014 layers: map[common.Hash]snapshot{ 1015 base.root: base, 1016 }, 1017 } 1018 snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), makeAccounts(2000), nil) 1019 for i := 2; i <= 100; i++ { 1020 snaps.Update(common.HexToHash(fmt.Sprintf("0x%02x", i+1)), common.HexToHash(fmt.Sprintf("0x%02x", i)), makeAccounts(20), nil) 1021 } 1022 // We call this once before the benchmark, so the creation of 1023 // sorted accountlists are not included in the results. 1024 head := snaps.Snapshot(common.HexToHash("0x65")) 1025 head.(*diffLayer).newBinaryAccountIterator(common.Hash{}) 1026 1027 b.Run("binary iterator (keys)", func(b *testing.B) { 1028 for i := 0; i < b.N; i++ { 1029 got := 0 1030 it := head.(*diffLayer).newBinaryAccountIterator(common.Hash{}) 1031 for it.Next() { 1032 got++ 1033 } 1034 if exp := 2000; got != exp { 1035 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 1036 } 1037 } 1038 }) 1039 b.Run("binary iterator (values)", func(b *testing.B) { 1040 for i := 0; i < b.N; i++ { 1041 got := 0 1042 it := head.(*diffLayer).newBinaryAccountIterator(common.Hash{}) 1043 for it.Next() { 1044 got++ 1045 v := it.Hash() 1046 head.(*diffLayer).accountRLP(v, 0) 1047 } 1048 if exp := 2000; got != exp { 1049 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 1050 } 1051 } 1052 }) 1053 b.Run("fast iterator (keys)", func(b *testing.B) { 1054 for i := 0; i < b.N; i++ { 1055 it, _ := snaps.AccountIterator(common.HexToHash("0x65"), common.Hash{}) 1056 defer it.Release() 1057 1058 got := 0 1059 for it.Next() { 1060 got++ 1061 } 1062 if exp := 2000; got != exp { 1063 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 1064 } 1065 } 1066 }) 1067 b.Run("fast iterator (values)", func(b *testing.B) { 1068 for i := 0; i < b.N; i++ { 1069 it, _ := snaps.AccountIterator(common.HexToHash("0x65"), common.Hash{}) 1070 defer it.Release() 1071 1072 got := 0 1073 for it.Next() { 1074 it.Account() 1075 got++ 1076 } 1077 if exp := 2000; got != exp { 1078 b.Errorf("iterator len wrong, expected %d, got %d", exp, got) 1079 } 1080 } 1081 }) 1082 } 1083 1084 /* 1085 func BenchmarkBinaryAccountIteration(b *testing.B) { 1086 benchmarkAccountIteration(b, func(snap snapshot) AccountIterator { 1087 return snap.(*diffLayer).newBinaryAccountIterator(common.Hash{}) 1088 }) 1089 } 1090 1091 func BenchmarkFastAccountIteration(b *testing.B) { 1092 benchmarkAccountIteration(b, newFastAccountIterator) 1093 } 1094 1095 func benchmarkAccountIteration(b *testing.B, iterator func(snap snapshot) AccountIterator) { 1096 // Create a diff stack and randomize the accounts across them 1097 layers := make([]map[common.Hash][]byte, 128) 1098 for i := 0; i < len(layers); i++ { 1099 layers[i] = make(map[common.Hash][]byte) 1100 } 1101 for i := 0; i < b.N; i++ { 1102 depth := rand.Intn(len(layers)) 1103 layers[depth][randomHash()] = randomAccount() 1104 } 1105 stack := snapshot(emptyLayer()) 1106 for _, layer := range layers { 1107 stack = stack.Update(common.Hash{}, layer, nil, nil) 1108 } 1109 // Reset the timers and report all the stats 1110 it := iterator(stack) 1111 1112 b.ResetTimer() 1113 b.ReportAllocs() 1114 1115 for it.Next() { 1116 } 1117 } 1118 */