github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/eth/filters/bench_test.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:38</date>
    10  //</624342635380740096>
    11  
    12  
    13  package filters
    14  
    15  import (
    16  	"bytes"
    17  	"context"
    18  	"fmt"
    19  	"testing"
    20  	"time"
    21  
    22  	"github.com/ethereum/go-ethereum/common"
    23  	"github.com/ethereum/go-ethereum/common/bitutil"
    24  	"github.com/ethereum/go-ethereum/core/bloombits"
    25  	"github.com/ethereum/go-ethereum/core/rawdb"
    26  	"github.com/ethereum/go-ethereum/core/types"
    27  	"github.com/ethereum/go-ethereum/ethdb"
    28  	"github.com/ethereum/go-ethereum/event"
    29  	"github.com/ethereum/go-ethereum/node"
    30  )
    31  
    32  func BenchmarkBloomBits512(b *testing.B) {
    33  	benchmarkBloomBits(b, 512)
    34  }
    35  
    36  func BenchmarkBloomBits1k(b *testing.B) {
    37  	benchmarkBloomBits(b, 1024)
    38  }
    39  
    40  func BenchmarkBloomBits2k(b *testing.B) {
    41  	benchmarkBloomBits(b, 2048)
    42  }
    43  
    44  func BenchmarkBloomBits4k(b *testing.B) {
    45  	benchmarkBloomBits(b, 4096)
    46  }
    47  
    48  func BenchmarkBloomBits8k(b *testing.B) {
    49  	benchmarkBloomBits(b, 8192)
    50  }
    51  
    52  func BenchmarkBloomBits16k(b *testing.B) {
    53  	benchmarkBloomBits(b, 16384)
    54  }
    55  
    56  func BenchmarkBloomBits32k(b *testing.B) {
    57  	benchmarkBloomBits(b, 32768)
    58  }
    59  
    60  const benchFilterCnt = 2000
    61  
    62  func benchmarkBloomBits(b *testing.B, sectionSize uint64) {
    63  	benchDataDir := node.DefaultDataDir() + "/geth/chaindata"
    64  	fmt.Println("Running bloombits benchmark   section size:", sectionSize)
    65  
    66  	db, err := ethdb.NewLDBDatabase(benchDataDir, 128, 1024)
    67  	if err != nil {
    68  		b.Fatalf("error opening database at %v: %v", benchDataDir, err)
    69  	}
    70  	head := rawdb.ReadHeadBlockHash(db)
    71  	if head == (common.Hash{}) {
    72  		b.Fatalf("chain data not found at %v", benchDataDir)
    73  	}
    74  
    75  	clearBloomBits(db)
    76  	fmt.Println("Generating bloombits data...")
    77  	headNum := rawdb.ReadHeaderNumber(db, head)
    78  	if headNum == nil || *headNum < sectionSize+512 {
    79  		b.Fatalf("not enough blocks for running a benchmark")
    80  	}
    81  
    82  	start := time.Now()
    83  	cnt := (*headNum - 512) / sectionSize
    84  	var dataSize, compSize uint64
    85  	for sectionIdx := uint64(0); sectionIdx < cnt; sectionIdx++ {
    86  		bc, err := bloombits.NewGenerator(uint(sectionSize))
    87  		if err != nil {
    88  			b.Fatalf("failed to create generator: %v", err)
    89  		}
    90  		var header *types.Header
    91  		for i := sectionIdx * sectionSize; i < (sectionIdx+1)*sectionSize; i++ {
    92  			hash := rawdb.ReadCanonicalHash(db, i)
    93  			header = rawdb.ReadHeader(db, hash, i)
    94  			if header == nil {
    95  				b.Fatalf("Error creating bloomBits data")
    96  			}
    97  			bc.AddBloom(uint(i-sectionIdx*sectionSize), header.Bloom)
    98  		}
    99  		sectionHead := rawdb.ReadCanonicalHash(db, (sectionIdx+1)*sectionSize-1)
   100  		for i := 0; i < types.BloomBitLength; i++ {
   101  			data, err := bc.Bitset(uint(i))
   102  			if err != nil {
   103  				b.Fatalf("failed to retrieve bitset: %v", err)
   104  			}
   105  			comp := bitutil.CompressBytes(data)
   106  			dataSize += uint64(len(data))
   107  			compSize += uint64(len(comp))
   108  			rawdb.WriteBloomBits(db, uint(i), sectionIdx, sectionHead, comp)
   109  		}
   110  //如果节IDX%50==0
   111  //fmt.println(“节”,节IDX,“/”,cnt)
   112  //}
   113  	}
   114  
   115  	d := time.Since(start)
   116  	fmt.Println("Finished generating bloombits data")
   117  	fmt.Println(" ", d, "total  ", d/time.Duration(cnt*sectionSize), "per block")
   118  	fmt.Println(" data size:", dataSize, "  compressed size:", compSize, "  compression ratio:", float64(compSize)/float64(dataSize))
   119  
   120  	fmt.Println("Running filter benchmarks...")
   121  	start = time.Now()
   122  	mux := new(event.TypeMux)
   123  	var backend *testBackend
   124  
   125  	for i := 0; i < benchFilterCnt; i++ {
   126  		if i%20 == 0 {
   127  			db.Close()
   128  			db, _ = ethdb.NewLDBDatabase(benchDataDir, 128, 1024)
   129  			backend = &testBackend{mux, db, cnt, new(event.Feed), new(event.Feed), new(event.Feed), new(event.Feed)}
   130  		}
   131  		var addr common.Address
   132  		addr[0] = byte(i)
   133  		addr[1] = byte(i / 256)
   134  		filter := NewRangeFilter(backend, 0, int64(cnt*sectionSize-1), []common.Address{addr}, nil)
   135  		if _, err := filter.Logs(context.Background()); err != nil {
   136  			b.Error("filter.Find error:", err)
   137  		}
   138  	}
   139  	d = time.Since(start)
   140  	fmt.Println("Finished running filter benchmarks")
   141  	fmt.Println(" ", d, "total  ", d/time.Duration(benchFilterCnt), "per address", d*time.Duration(1000000)/time.Duration(benchFilterCnt*cnt*sectionSize), "per million blocks")
   142  	db.Close()
   143  }
   144  
   145  func forEachKey(db ethdb.Database, startPrefix, endPrefix []byte, fn func(key []byte)) {
   146  	it := db.(*ethdb.LDBDatabase).NewIterator()
   147  	it.Seek(startPrefix)
   148  	for it.Valid() {
   149  		key := it.Key()
   150  		cmpLen := len(key)
   151  		if len(endPrefix) < cmpLen {
   152  			cmpLen = len(endPrefix)
   153  		}
   154  		if bytes.Compare(key[:cmpLen], endPrefix) == 1 {
   155  			break
   156  		}
   157  		fn(common.CopyBytes(key))
   158  		it.Next()
   159  	}
   160  	it.Release()
   161  }
   162  
   163  var bloomBitsPrefix = []byte("bloomBits-")
   164  
   165  func clearBloomBits(db ethdb.Database) {
   166  	fmt.Println("Clearing bloombits data...")
   167  	forEachKey(db, bloomBitsPrefix, bloomBitsPrefix, func(key []byte) {
   168  		db.Delete(key)
   169  	})
   170  }
   171  
   172  func BenchmarkNoBloomBits(b *testing.B) {
   173  	benchDataDir := node.DefaultDataDir() + "/geth/chaindata"
   174  	fmt.Println("Running benchmark without bloombits")
   175  	db, err := ethdb.NewLDBDatabase(benchDataDir, 128, 1024)
   176  	if err != nil {
   177  		b.Fatalf("error opening database at %v: %v", benchDataDir, err)
   178  	}
   179  	head := rawdb.ReadHeadBlockHash(db)
   180  	if head == (common.Hash{}) {
   181  		b.Fatalf("chain data not found at %v", benchDataDir)
   182  	}
   183  	headNum := rawdb.ReadHeaderNumber(db, head)
   184  
   185  	clearBloomBits(db)
   186  
   187  	fmt.Println("Running filter benchmarks...")
   188  	start := time.Now()
   189  	mux := new(event.TypeMux)
   190  	backend := &testBackend{mux, db, 0, new(event.Feed), new(event.Feed), new(event.Feed), new(event.Feed)}
   191  	filter := NewRangeFilter(backend, 0, int64(*headNum), []common.Address{{}}, nil)
   192  	filter.Logs(context.Background())
   193  	d := time.Since(start)
   194  	fmt.Println("Finished running filter benchmarks")
   195  	fmt.Println(" ", d, "total  ", d*time.Duration(1000000)/time.Duration(*headNum+1), "per million blocks")
   196  	db.Close()
   197  }
   198