瀏覽代碼

core: add InsertChain benchmarks

Felix Lange 10 年之前
父節點
當前提交
c3d6228023
共有 1 個文件被更改,包括 149 次插入0 次删除
  1. 149 0
      core/bench_test.go

+ 149 - 0
core/bench_test.go

@@ -0,0 +1,149 @@
+package core
+
+import (
+	"crypto/ecdsa"
+	"io/ioutil"
+	"math/big"
+	"os"
+	"testing"
+
+	"github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/core/types"
+	"github.com/ethereum/go-ethereum/crypto"
+	"github.com/ethereum/go-ethereum/ethdb"
+	"github.com/ethereum/go-ethereum/event"
+	"github.com/ethereum/go-ethereum/params"
+)
+
+func BenchmarkInsertChain_empty_memdb(b *testing.B) {
+	benchInsertChain(b, false, nil)
+}
+func BenchmarkInsertChain_empty_diskdb(b *testing.B) {
+	benchInsertChain(b, true, nil)
+}
+func BenchmarkInsertChain_valueTx_memdb(b *testing.B) {
+	benchInsertChain(b, false, genValueTx(0))
+}
+func BenchmarkInsertChain_valueTx_diskdb(b *testing.B) {
+	benchInsertChain(b, true, genValueTx(0))
+}
+func BenchmarkInsertChain_valueTx_100kB_memdb(b *testing.B) {
+	benchInsertChain(b, false, genValueTx(100*1024))
+}
+func BenchmarkInsertChain_valueTx_100kB_diskdb(b *testing.B) {
+	benchInsertChain(b, true, genValueTx(100*1024))
+}
+func BenchmarkInsertChain_uncles_memdb(b *testing.B) {
+	benchInsertChain(b, false, genUncles)
+}
+func BenchmarkInsertChain_uncles_diskdb(b *testing.B) {
+	benchInsertChain(b, true, genUncles)
+}
+func BenchmarkInsertChain_ring200_memdb(b *testing.B) {
+	benchInsertChain(b, false, genTxRing(200))
+}
+func BenchmarkInsertChain_ring200_diskdb(b *testing.B) {
+	benchInsertChain(b, true, genTxRing(200))
+}
+func BenchmarkInsertChain_ring1000_memdb(b *testing.B) {
+	benchInsertChain(b, false, genTxRing(1000))
+}
+func BenchmarkInsertChain_ring1000_diskdb(b *testing.B) {
+	benchInsertChain(b, true, genTxRing(1000))
+}
+
+var (
+	// This is the content of the genesis block used by the benchmarks.
+	benchRootKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+	benchRootAddr   = crypto.PubkeyToAddress(benchRootKey.PublicKey)
+	benchRootFunds  = common.BigPow(2, 100)
+)
+
+// genValueTx returns a block generator that includes a single
+// value-transfer transaction with n bytes of extra data in each
+// block.
+func genValueTx(nbytes int) func(int, *BlockGen) {
+	return func(i int, gen *BlockGen) {
+		toaddr := common.Address{}
+		data := make([]byte, nbytes)
+		gas := IntrinsicGas(data)
+		tx, _ := types.NewTransaction(gen.TxNonce(benchRootAddr), toaddr, big.NewInt(1), gas, nil, data).SignECDSA(benchRootKey)
+		gen.AddTx(tx)
+	}
+}
+
+// genTxRing returns a block generator that sends ether in a ring
+// among n accounts. This is creates n entries in the state database
+// and fills the blocks with many small transactions.
+func genTxRing(naccounts int) func(int, *BlockGen) {
+	keys := make([]*ecdsa.PrivateKey, naccounts)
+	keys[0] = benchRootKey
+	for i := 1; i < naccounts; i++ {
+		keys[i], _ = crypto.GenerateKey()
+	}
+
+	from := 0
+	return func(i int, gen *BlockGen) {
+		gas := CalcGasLimit(gen.PrevBlock(i - 1))
+		for {
+			gas.Sub(gas, params.TxGas)
+			if gas.Cmp(params.TxGas) < 0 {
+				break
+			}
+			to := (from + 1) % naccounts
+			fromaddr := crypto.PubkeyToAddress(keys[from].PublicKey)
+			toaddr := crypto.PubkeyToAddress(keys[to].PublicKey)
+			tx, _ := types.NewTransaction(gen.TxNonce(fromaddr), toaddr, benchRootFunds, params.TxGas, nil, nil).SignECDSA(keys[from])
+			gen.AddTx(tx)
+			from = to
+		}
+	}
+}
+
+// genUncles generates blocks with two uncle headers.
+func genUncles(i int, gen *BlockGen) {
+	if i >= 6 {
+		b2 := gen.PrevBlock(i - 6).Header()
+		b2.Extra = []byte("foo")
+		gen.AddUncle(b2)
+		b3 := gen.PrevBlock(i - 6).Header()
+		b3.Extra = []byte("bar")
+		gen.AddUncle(b3)
+	}
+}
+
+func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
+	// Create the database in memory or in a temporary directory.
+	var db common.Database
+	if !disk {
+		db, _ = ethdb.NewMemDatabase()
+	} else {
+		dir, err := ioutil.TempDir("", "eth-core-bench")
+		if err != nil {
+			b.Fatalf("cannot create temporary directory: %v", err)
+		}
+		defer os.RemoveAll(dir)
+		db, err = ethdb.NewLDBDatabase(dir)
+		if err != nil {
+			b.Fatalf("cannot create temporary database: %v", err)
+		}
+		defer db.Close()
+	}
+
+	// Generate a chain of b.N blocks using the supplied block
+	// generator function.
+	genesis := GenesisBlockForTesting(db, benchRootAddr, benchRootFunds)
+	chain := GenerateChain(genesis, db, b.N, gen)
+
+	// Time the insertion of the new chain.
+	// State and blocks are stored in the same DB.
+	evmux := new(event.TypeMux)
+	chainman, _ := NewChainManager(genesis, db, db, FakePow{}, evmux)
+	chainman.SetProcessor(NewBlockProcessor(db, db, FakePow{}, chainman, evmux))
+	defer chainman.Stop()
+	b.ReportAllocs()
+	b.ResetTimer()
+	if i, err := chainman.InsertChain(chain); err != nil {
+		b.Fatalf("insert error (block %d): %v\n", i, err)
+	}
+}