diff --git a/core/bench_test.go b/core/bench_test.go index ac5b57bc8..1ecd87cbd 100644 --- a/core/bench_test.go +++ b/core/bench_test.go @@ -176,3 +176,122 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) { b.Fatalf("insert error (block %d): %v\n", i, err) } } + +func BenchmarkChainRead_header_10k(b *testing.B) { + benchReadChain(b, false, 10000) +} +func BenchmarkChainRead_full_10k(b *testing.B) { + benchReadChain(b, true, 10000) +} +func BenchmarkChainRead_header_100k(b *testing.B) { + benchReadChain(b, false, 100000) +} +func BenchmarkChainRead_full_100k(b *testing.B) { + benchReadChain(b, true, 100000) +} +func BenchmarkChainRead_header_500k(b *testing.B) { + benchReadChain(b, false, 500000) +} +func BenchmarkChainRead_full_500k(b *testing.B) { + benchReadChain(b, true, 500000) +} +func BenchmarkChainWrite_header_10k(b *testing.B) { + benchWriteChain(b, false, 10000) +} +func BenchmarkChainWrite_full_10k(b *testing.B) { + benchWriteChain(b, true, 10000) +} +func BenchmarkChainWrite_header_100k(b *testing.B) { + benchWriteChain(b, false, 100000) +} +func BenchmarkChainWrite_full_100k(b *testing.B) { + benchWriteChain(b, true, 100000) +} +func BenchmarkChainWrite_header_500k(b *testing.B) { + benchWriteChain(b, false, 500000) +} +func BenchmarkChainWrite_full_500k(b *testing.B) { + benchWriteChain(b, true, 500000) +} + +// makeChainForBench writes a given number of headers or empty blocks/receipts +// into a database. +func makeChainForBench(db ethdb.Database, full bool, count uint64) { + var hash common.Hash + for n := uint64(0); n < count; n++ { + header := &types.Header{ + Coinbase: common.Address{}, + Number: big.NewInt(int64(n)), + ParentHash: hash, + Difficulty: big.NewInt(1), + UncleHash: types.EmptyUncleHash, + TxHash: types.EmptyRootHash, + ReceiptHash: types.EmptyRootHash, + } + hash = header.Hash() + WriteHeader(db, header) + WriteCanonicalHash(db, hash, n) + WriteTd(db, hash, big.NewInt(int64(n+1))) + if full || n == 0 { + block := types.NewBlockWithHeader(header) + WriteBody(db, hash, block.Body()) + WriteBlockReceipts(db, hash, nil) + } + } +} + +func benchWriteChain(b *testing.B, full bool, count uint64) { + for i := 0; i < b.N; i++ { + dir, err := ioutil.TempDir("", "eth-chain-bench") + if err != nil { + b.Fatalf("cannot create temporary directory: %v", err) + } + db, err := ethdb.NewLDBDatabase(dir, 128, 1024) + if err != nil { + b.Fatalf("error opening database at %v: %v", dir, err) + } + makeChainForBench(db, full, count) + db.Close() + os.RemoveAll(dir) + } +} + +func benchReadChain(b *testing.B, full bool, count uint64) { + dir, err := ioutil.TempDir("", "eth-chain-bench") + if err != nil { + b.Fatalf("cannot create temporary directory: %v", err) + } + defer os.RemoveAll(dir) + + db, err := ethdb.NewLDBDatabase(dir, 128, 1024) + if err != nil { + b.Fatalf("error opening database at %v: %v", dir, err) + } + makeChainForBench(db, full, count) + db.Close() + + b.ReportAllocs() + b.ResetTimer() + + for i := 0; i < b.N; i++ { + db, err := ethdb.NewLDBDatabase(dir, 128, 1024) + if err != nil { + b.Fatalf("error opening database at %v: %v", dir, err) + } + chain, err := NewBlockChain(db, testChainConfig(), FakePow{}, new(event.TypeMux)) + if err != nil { + b.Fatalf("error creating chain: %v", err) + } + + for n := uint64(0); n < count; n++ { + header := chain.GetHeaderByNumber(n) + if full { + hash := header.Hash() + GetBody(db, hash) + GetBlockReceipts(db, hash) + } + } + + db.Close() + } +}