|
|
|
// Copyright 2019 The go-ethereum Authors
|
|
|
|
// This file is part of the go-ethereum library.
|
|
|
|
//
|
|
|
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
|
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
package pathdb
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
|
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
|
|
|
"github.com/ethereum/go-ethereum/crypto"
|
|
|
|
"github.com/ethereum/go-ethereum/internal/testrand"
|
|
|
|
"github.com/ethereum/go-ethereum/trie/trienode"
|
|
|
|
)
|
|
|
|
|
|
|
|
func emptyLayer() *diskLayer {
|
|
|
|
return &diskLayer{
|
|
|
|
db: New(rawdb.NewMemoryDatabase(), nil, false),
|
all: activate pbss as experimental feature (#26274)
* all: activate pbss
* core/rawdb: fix compilation error
* cma, core, eth, les, trie: address comments
* cmd, core, eth, trie: polish code
* core, cmd, eth: address comments
* cmd, core, eth, les, light, tests: address comment
* cmd/utils: shorten log message
* trie/triedb/pathdb: limit node buffer size to 1gb
* cmd/utils: fix opening non-existing db
* cmd/utils: rename flag name
* cmd, core: group chain history flags and fix tests
* core, eth, trie: fix memory leak in snapshot generation
* cmd, eth, internal: deprecate flags
* all: enable state tests for pathdb, fixes
* cmd, core: polish code
* trie/triedb/pathdb: limit the node buffer size to 256mb
---------
Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
1 year ago
|
|
|
buffer: newNodeBuffer(DefaultBufferSize, nil, 0),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// goos: darwin
|
|
|
|
// goarch: arm64
|
|
|
|
// pkg: github.com/ethereum/go-ethereum/trie
|
|
|
|
// BenchmarkSearch128Layers
|
|
|
|
// BenchmarkSearch128Layers-8 243826 4755 ns/op
|
|
|
|
func BenchmarkSearch128Layers(b *testing.B) { benchmarkSearch(b, 0, 128) }
|
|
|
|
|
|
|
|
// goos: darwin
|
|
|
|
// goarch: arm64
|
|
|
|
// pkg: github.com/ethereum/go-ethereum/trie
|
|
|
|
// BenchmarkSearch512Layers
|
|
|
|
// BenchmarkSearch512Layers-8 49686 24256 ns/op
|
|
|
|
func BenchmarkSearch512Layers(b *testing.B) { benchmarkSearch(b, 0, 512) }
|
|
|
|
|
|
|
|
// goos: darwin
|
|
|
|
// goarch: arm64
|
|
|
|
// pkg: github.com/ethereum/go-ethereum/trie
|
|
|
|
// BenchmarkSearch1Layer
|
|
|
|
// BenchmarkSearch1Layer-8 14062725 88.40 ns/op
|
|
|
|
func BenchmarkSearch1Layer(b *testing.B) { benchmarkSearch(b, 127, 128) }
|
|
|
|
|
|
|
|
func benchmarkSearch(b *testing.B, depth int, total int) {
|
|
|
|
var (
|
|
|
|
npath []byte
|
|
|
|
nblob []byte
|
|
|
|
)
|
|
|
|
// First, we set up 128 diff layers, with 3K items each
|
|
|
|
fill := func(parent layer, index int) *diffLayer {
|
|
|
|
nodes := make(map[common.Hash]map[string]*trienode.Node)
|
|
|
|
nodes[common.Hash{}] = make(map[string]*trienode.Node)
|
|
|
|
for i := 0; i < 3000; i++ {
|
|
|
|
var (
|
|
|
|
path = testrand.Bytes(32)
|
|
|
|
blob = testrand.Bytes(100)
|
|
|
|
node = trienode.New(crypto.Keccak256Hash(blob), blob)
|
|
|
|
)
|
|
|
|
nodes[common.Hash{}][string(path)] = node
|
|
|
|
if npath == nil && depth == index {
|
|
|
|
npath = common.CopyBytes(path)
|
|
|
|
nblob = common.CopyBytes(blob)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return newDiffLayer(parent, common.Hash{}, 0, 0, nodes, nil)
|
|
|
|
}
|
|
|
|
var layer layer
|
|
|
|
layer = emptyLayer()
|
|
|
|
for i := 0; i < total; i++ {
|
|
|
|
layer = fill(layer, i)
|
|
|
|
}
|
|
|
|
b.ResetTimer()
|
|
|
|
|
|
|
|
var (
|
|
|
|
have []byte
|
|
|
|
err error
|
|
|
|
)
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
have, _, _, err = layer.node(common.Hash{}, npath, 0)
|
|
|
|
if err != nil {
|
|
|
|
b.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !bytes.Equal(have, nblob) {
|
|
|
|
b.Fatalf("have %x want %x", have, nblob)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// goos: darwin
|
|
|
|
// goarch: arm64
|
|
|
|
// pkg: github.com/ethereum/go-ethereum/trie
|
|
|
|
// BenchmarkPersist
|
|
|
|
// BenchmarkPersist-8 10 111252975 ns/op
|
|
|
|
func BenchmarkPersist(b *testing.B) {
|
|
|
|
// First, we set up 128 diff layers, with 3K items each
|
|
|
|
fill := func(parent layer) *diffLayer {
|
|
|
|
nodes := make(map[common.Hash]map[string]*trienode.Node)
|
|
|
|
nodes[common.Hash{}] = make(map[string]*trienode.Node)
|
|
|
|
for i := 0; i < 3000; i++ {
|
|
|
|
var (
|
|
|
|
path = testrand.Bytes(32)
|
|
|
|
blob = testrand.Bytes(100)
|
|
|
|
node = trienode.New(crypto.Keccak256Hash(blob), blob)
|
|
|
|
)
|
|
|
|
nodes[common.Hash{}][string(path)] = node
|
|
|
|
}
|
|
|
|
return newDiffLayer(parent, common.Hash{}, 0, 0, nodes, nil)
|
|
|
|
}
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
b.StopTimer()
|
|
|
|
var layer layer
|
|
|
|
layer = emptyLayer()
|
|
|
|
for i := 1; i < 128; i++ {
|
|
|
|
layer = fill(layer)
|
|
|
|
}
|
|
|
|
b.StartTimer()
|
|
|
|
|
|
|
|
dl, ok := layer.(*diffLayer)
|
|
|
|
if !ok {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
dl.persist(false)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// BenchmarkJournal benchmarks the performance for journaling the layers.
|
|
|
|
//
|
|
|
|
// BenchmarkJournal
|
|
|
|
// BenchmarkJournal-8 10 110969279 ns/op
|
|
|
|
func BenchmarkJournal(b *testing.B) {
|
|
|
|
b.SkipNow()
|
|
|
|
|
|
|
|
// First, we set up 128 diff layers, with 3K items each
|
|
|
|
fill := func(parent layer) *diffLayer {
|
|
|
|
nodes := make(map[common.Hash]map[string]*trienode.Node)
|
|
|
|
nodes[common.Hash{}] = make(map[string]*trienode.Node)
|
|
|
|
for i := 0; i < 3000; i++ {
|
|
|
|
var (
|
|
|
|
path = testrand.Bytes(32)
|
|
|
|
blob = testrand.Bytes(100)
|
|
|
|
node = trienode.New(crypto.Keccak256Hash(blob), blob)
|
|
|
|
)
|
|
|
|
nodes[common.Hash{}][string(path)] = node
|
|
|
|
}
|
|
|
|
// TODO(rjl493456442) a non-nil state set is expected.
|
|
|
|
return newDiffLayer(parent, common.Hash{}, 0, 0, nodes, nil)
|
|
|
|
}
|
|
|
|
var layer layer
|
|
|
|
layer = emptyLayer()
|
|
|
|
for i := 0; i < 128; i++ {
|
|
|
|
layer = fill(layer)
|
|
|
|
}
|
|
|
|
b.ResetTimer()
|
|
|
|
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
layer.journal(new(bytes.Buffer))
|
|
|
|
}
|
|
|
|
}
|