bnb-chain / node

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Experiment on applying block that already in local disk

unclezoro opened this issue · comments

commented

Level db

How to start

./bnbchaind start --home ./testnoded

The log

I[2020-03-03|07:49:38.128] start to collect publish information         module=pub height=1

I[2020-03-03|07:49:52.625] Executed block                               module=consensus height=10000 validTxs=0 invalidTxs=0

I[2020-03-03|07:53:20.049] Executed block                               module=consensus height=13364 validTxs=0 invalidTxs=0

Analysis

The first 10000 block is very quick, only use 14 second. But after that the speed slow down to 16 blocks/second quickly. This is possibly related to the prune strategy, we have discussed in the #551, the speed of no prune is 3 times faster than prune in the long run.

Mem db

How to start

./bnbchaind start --home ./testnoded --pruning everything &, Have to use prune everything strategy to avoid memory usage grow huge.

Also need change the code in main.go a bit:

func newApp(logger log.Logger, db dbm.DB, storeTracer io.Writer) abci.Application {
	mendb := dbm.NewMemDB()
	return app.NewBinanceChain(logger, mendb, storeTracer)
}

Proof that use memdb indeed:

$du -l --max-depth=1
20      ./evidence.db
16220   ./state.db
61544   ./blockstore.db
20      ./tx_index.db
16      ./application.db  #it is empty when use mem db, even start with no prune strategy
11660   ./application.db_back  #level db

The log

I[2020-03-03|08:02:50.461] Executed block                               module=consensus height=1 validTxs=0 invalidTxs=0
I[2020-03-03|08:02:55.230] Executed block                               module=consensus height=1000 validTxs=0 invalidTxs=0
I[2020-03-03|08:04:41.864] start to collect publish information         module=pub height=5000
I[2020-03-03|08:08:36.001] start to collect publish information         module=pub height=8725

Analysis

The first 1000 block, it is quick. But after 5000 block, only 15.8 blocks/second.

Reason:
We can see that the bnbchaind process use 100 CPU resouces (means one core), we doubt that
there is one routine that is serial and cpu intensive.
We profile the cpu usage for 120seconds, and get that:
image

Each time commit wil save SaveOrphans:

func (ndb *nodeDB) SaveOrphans(version int64, orphans map[string]int64) {
	....
	toVersion := ndb.getPreviousVersion(version)
        ....
func (ndb *nodeDB) getPreviousVersion(version int64) int64 {
	itr := ndb.db.ReverseIterator(
		rootKeyFormat.Key(1),
		rootKeyFormat.Key(version),
	)
	...

	return 0
}
func (db *MemDB) ReverseIterator(start, end []byte) Iterator {
         ....
	keys := db.getSortedKeys(start, end, true)
	return newMemDBIterator(db, keys, start, end)
}
func (db *MemDB) getSortedKeys(start, end []byte, reverse bool) []string {
	keys := []string{}
	for key := range db.db {
                 inDomain := IsKeyInDomain([]byte(key), start, end)
		....
	}
	sort.Strings(keys)
         ...
        reurn keys
}

And let's see what is memdb's structure:

type MemDB struct {
	mtx sync.Mutex
	db  map[string][]byte
}

It means will iterate all the keys in db when save SaveOrphans, obviously IsKeyInDomain and sort.Strings(keys) functions is cpu intensive