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  */