github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/core/bench_test.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //版权所有2015 Go Ethereum作者
    10  //此文件是Go以太坊库的一部分。
    11  //
    12  //Go-Ethereum库是免费软件:您可以重新分发它和/或修改
    13  //根据GNU发布的较低通用公共许可证的条款
    14  //自由软件基金会,或者许可证的第3版,或者
    15  //(由您选择)任何更高版本。
    16  //
    17  //Go以太坊图书馆的发行目的是希望它会有用,
    18  //但没有任何保证;甚至没有
    19  //适销性或特定用途的适用性。见
    20  //GNU较低的通用公共许可证,了解更多详细信息。
    21  //
    22  //你应该收到一份GNU较低级别的公共许可证副本
    23  //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。
    24  
    25  package core
    26  
    27  import (
    28  	"crypto/ecdsa"
    29  	"io/ioutil"
    30  	"math/big"
    31  	"os"
    32  	"testing"
    33  
    34  	"github.com/ethereum/go-ethereum/common"
    35  	"github.com/ethereum/go-ethereum/common/math"
    36  	"github.com/ethereum/go-ethereum/consensus/ethash"
    37  	"github.com/ethereum/go-ethereum/core/rawdb"
    38  	"github.com/ethereum/go-ethereum/core/types"
    39  	"github.com/ethereum/go-ethereum/core/vm"
    40  	"github.com/ethereum/go-ethereum/crypto"
    41  	"github.com/ethereum/go-ethereum/ethdb"
    42  	"github.com/ethereum/go-ethereum/params"
    43  )
    44  
    45  func BenchmarkInsertChain_empty_memdb(b *testing.B) {
    46  	benchInsertChain(b, false, nil)
    47  }
    48  func BenchmarkInsertChain_empty_diskdb(b *testing.B) {
    49  	benchInsertChain(b, true, nil)
    50  }
    51  func BenchmarkInsertChain_valueTx_memdb(b *testing.B) {
    52  	benchInsertChain(b, false, genValueTx(0))
    53  }
    54  func BenchmarkInsertChain_valueTx_diskdb(b *testing.B) {
    55  	benchInsertChain(b, true, genValueTx(0))
    56  }
    57  func BenchmarkInsertChain_valueTx_100kB_memdb(b *testing.B) {
    58  	benchInsertChain(b, false, genValueTx(100*1024))
    59  }
    60  func BenchmarkInsertChain_valueTx_100kB_diskdb(b *testing.B) {
    61  	benchInsertChain(b, true, genValueTx(100*1024))
    62  }
    63  func BenchmarkInsertChain_uncles_memdb(b *testing.B) {
    64  	benchInsertChain(b, false, genUncles)
    65  }
    66  func BenchmarkInsertChain_uncles_diskdb(b *testing.B) {
    67  	benchInsertChain(b, true, genUncles)
    68  }
    69  func BenchmarkInsertChain_ring200_memdb(b *testing.B) {
    70  	benchInsertChain(b, false, genTxRing(200))
    71  }
    72  func BenchmarkInsertChain_ring200_diskdb(b *testing.B) {
    73  	benchInsertChain(b, true, genTxRing(200))
    74  }
    75  func BenchmarkInsertChain_ring1000_memdb(b *testing.B) {
    76  	benchInsertChain(b, false, genTxRing(1000))
    77  }
    78  func BenchmarkInsertChain_ring1000_diskdb(b *testing.B) {
    79  	benchInsertChain(b, true, genTxRing(1000))
    80  }
    81  
    82  var (
    83  //这是基准使用的Genesis块的内容。
    84  	benchRootKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
    85  	benchRootAddr   = crypto.PubkeyToAddress(benchRootKey.PublicKey)
    86  	benchRootFunds  = math.BigPow(2, 100)
    87  )
    88  
    89  //
    90  //值传输事务,每个事务中有n个字节的额外数据
    91  //块。
    92  func genValueTx(nbytes int) func(int, *BlockGen) {
    93  	return func(i int, gen *BlockGen) {
    94  		toaddr := common.Address{}
    95  		data := make([]byte, nbytes)
    96  		gas, _ := IntrinsicGas(data, false, false)
    97  		tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(benchRootAddr), toaddr, big.NewInt(1), gas, nil, data), types.HomesteadSigner{}, benchRootKey)
    98  		gen.AddTx(tx)
    99  	}
   100  }
   101  
   102  var (
   103  	ringKeys  = make([]*ecdsa.PrivateKey, 1000)
   104  	ringAddrs = make([]common.Address, len(ringKeys))
   105  )
   106  
   107  func init() {
   108  	ringKeys[0] = benchRootKey
   109  	ringAddrs[0] = benchRootAddr
   110  	for i := 1; i < len(ringKeys); i++ {
   111  		ringKeys[i], _ = crypto.GenerateKey()
   112  		ringAddrs[i] = crypto.PubkeyToAddress(ringKeys[i].PublicKey)
   113  	}
   114  }
   115  
   116  //Gentxring返回一个以环形方式发送乙醚的块生成器
   117  //在N个帐户中。这是在状态数据库中创建n个条目
   118  //并用许多小事务填充块。
   119  func genTxRing(naccounts int) func(int, *BlockGen) {
   120  	from := 0
   121  	return func(i int, gen *BlockGen) {
   122  		gas := CalcGasLimit(gen.PrevBlock(i - 1))
   123  		for {
   124  			gas -= params.TxGas
   125  			if gas < params.TxGas {
   126  				break
   127  			}
   128  			to := (from + 1) % naccounts
   129  			tx := types.NewTransaction(
   130  				gen.TxNonce(ringAddrs[from]),
   131  				ringAddrs[to],
   132  				benchRootFunds,
   133  				params.TxGas,
   134  				nil,
   135  				nil,
   136  			)
   137  			tx, _ = types.SignTx(tx, types.HomesteadSigner{}, ringKeys[from])
   138  			gen.AddTx(tx)
   139  			from = to
   140  		}
   141  	}
   142  }
   143  
   144  //
   145  func genUncles(i int, gen *BlockGen) {
   146  	if i >= 6 {
   147  		b2 := gen.PrevBlock(i - 6).Header()
   148  		b2.Extra = []byte("foo")
   149  		gen.AddUncle(b2)
   150  		b3 := gen.PrevBlock(i - 6).Header()
   151  		b3.Extra = []byte("bar")
   152  		gen.AddUncle(b3)
   153  	}
   154  }
   155  
   156  func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
   157  //在内存或临时目录中创建数据库。
   158  	var db ethdb.Database
   159  	if !disk {
   160  		db = ethdb.NewMemDatabase()
   161  	} else {
   162  		dir, err := ioutil.TempDir("", "eth-core-bench")
   163  		if err != nil {
   164  			b.Fatalf("cannot create temporary directory: %v", err)
   165  		}
   166  		defer os.RemoveAll(dir)
   167  		db, err = ethdb.NewLDBDatabase(dir, 128, 128)
   168  		if err != nil {
   169  			b.Fatalf("cannot create temporary database: %v", err)
   170  		}
   171  		defer db.Close()
   172  	}
   173  
   174  //使用提供的块生成B.N块链
   175  //发电机功能。
   176  	gspec := Genesis{
   177  		Config: params.TestChainConfig,
   178  		Alloc:  GenesisAlloc{benchRootAddr: {Balance: benchRootFunds}},
   179  	}
   180  	genesis := gspec.MustCommit(db)
   181  	chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, b.N, gen)
   182  
   183  //给插入新链条计时。
   184  //状态和块存储在同一个数据库中。
   185  	chainman, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
   186  	defer chainman.Stop()
   187  	b.ReportAllocs()
   188  	b.ResetTimer()
   189  	if i, err := chainman.InsertChain(chain); err != nil {
   190  		b.Fatalf("insert error (block %d): %v\n", i, err)
   191  	}
   192  }
   193  
   194  func BenchmarkChainRead_header_10k(b *testing.B) {
   195  	benchReadChain(b, false, 10000)
   196  }
   197  func BenchmarkChainRead_full_10k(b *testing.B) {
   198  	benchReadChain(b, true, 10000)
   199  }
   200  func BenchmarkChainRead_header_100k(b *testing.B) {
   201  	benchReadChain(b, false, 100000)
   202  }
   203  func BenchmarkChainRead_full_100k(b *testing.B) {
   204  	benchReadChain(b, true, 100000)
   205  }
   206  func BenchmarkChainRead_header_500k(b *testing.B) {
   207  	benchReadChain(b, false, 500000)
   208  }
   209  func BenchmarkChainRead_full_500k(b *testing.B) {
   210  	benchReadChain(b, true, 500000)
   211  }
   212  func BenchmarkChainWrite_header_10k(b *testing.B) {
   213  	benchWriteChain(b, false, 10000)
   214  }
   215  func BenchmarkChainWrite_full_10k(b *testing.B) {
   216  	benchWriteChain(b, true, 10000)
   217  }
   218  func BenchmarkChainWrite_header_100k(b *testing.B) {
   219  	benchWriteChain(b, false, 100000)
   220  }
   221  func BenchmarkChainWrite_full_100k(b *testing.B) {
   222  	benchWriteChain(b, true, 100000)
   223  }
   224  func BenchmarkChainWrite_header_500k(b *testing.B) {
   225  	benchWriteChain(b, false, 500000)
   226  }
   227  func BenchmarkChainWrite_full_500k(b *testing.B) {
   228  	benchWriteChain(b, true, 500000)
   229  }
   230  
   231  //makechainforbench写入给定数量的头或空块/收据
   232  //进入数据库。
   233  func makeChainForBench(db ethdb.Database, full bool, count uint64) {
   234  	var hash common.Hash
   235  	for n := uint64(0); n < count; n++ {
   236  		header := &types.Header{
   237  			Coinbase:    common.Address{},
   238  			Number:      big.NewInt(int64(n)),
   239  			ParentHash:  hash,
   240  			Difficulty:  big.NewInt(1),
   241  			UncleHash:   types.EmptyUncleHash,
   242  			TxHash:      types.EmptyRootHash,
   243  			ReceiptHash: types.EmptyRootHash,
   244  		}
   245  		hash = header.Hash()
   246  
   247  		rawdb.WriteHeader(db, header)
   248  		rawdb.WriteCanonicalHash(db, hash, n)
   249  		rawdb.WriteTd(db, hash, n, big.NewInt(int64(n+1)))
   250  
   251  		if full || n == 0 {
   252  			block := types.NewBlockWithHeader(header)
   253  			rawdb.WriteBody(db, hash, n, block.Body())
   254  			rawdb.WriteReceipts(db, hash, n, nil)
   255  		}
   256  	}
   257  }
   258  
   259  func benchWriteChain(b *testing.B, full bool, count uint64) {
   260  	for i := 0; i < b.N; i++ {
   261  		dir, err := ioutil.TempDir("", "eth-chain-bench")
   262  		if err != nil {
   263  			b.Fatalf("cannot create temporary directory: %v", err)
   264  		}
   265  		db, err := ethdb.NewLDBDatabase(dir, 128, 1024)
   266  		if err != nil {
   267  			b.Fatalf("error opening database at %v: %v", dir, err)
   268  		}
   269  		makeChainForBench(db, full, count)
   270  		db.Close()
   271  		os.RemoveAll(dir)
   272  	}
   273  }
   274  
   275  func benchReadChain(b *testing.B, full bool, count uint64) {
   276  	dir, err := ioutil.TempDir("", "eth-chain-bench")
   277  	if err != nil {
   278  		b.Fatalf("cannot create temporary directory: %v", err)
   279  	}
   280  	defer os.RemoveAll(dir)
   281  
   282  	db, err := ethdb.NewLDBDatabase(dir, 128, 1024)
   283  	if err != nil {
   284  		b.Fatalf("error opening database at %v: %v", dir, err)
   285  	}
   286  	makeChainForBench(db, full, count)
   287  	db.Close()
   288  
   289  	b.ReportAllocs()
   290  	b.ResetTimer()
   291  
   292  	for i := 0; i < b.N; i++ {
   293  		db, err := ethdb.NewLDBDatabase(dir, 128, 1024)
   294  		if err != nil {
   295  			b.Fatalf("error opening database at %v: %v", dir, err)
   296  		}
   297  		chain, err := NewBlockChain(db, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{})
   298  		if err != nil {
   299  			b.Fatalf("error creating chain: %v", err)
   300  		}
   301  
   302  		for n := uint64(0); n < count; n++ {
   303  			header := chain.GetHeaderByNumber(n)
   304  			if full {
   305  				hash := header.Hash()
   306  				rawdb.ReadBody(db, hash, n)
   307  				rawdb.ReadReceipts(db, hash, n)
   308  			}
   309  		}
   310  		chain.Stop()
   311  		db.Close()
   312  	}
   313  }