core: add InsertChain benchmarks
This commit is contained in:
		
				
					committed by
					
						 Jeffrey Wilcke
						Jeffrey Wilcke
					
				
			
			
				
	
			
			
			
						parent
						
							7098ec691c
						
					
				
				
					commit
					c3d6228023
				
			
							
								
								
									
										149
									
								
								core/bench_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								core/bench_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -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) | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user