From 4a472a8b54a38dc1e325bca6f20761e7fa770d48 Mon Sep 17 00:00:00 2001 From: Jeffrey Wilcke Date: Fri, 17 Jul 2015 15:43:16 +0200 Subject: [PATCH] ip --- cmd/geth/main.go | 5 +++++ core/chain_manager.go | 22 --------------------- core/transaction_util.go | 42 ++++++++++++++++++++++++++++++++++++---- ethdb/database.go | 5 ++++- trie/hashnode.go | 2 +- trie/trie.go | 6 ++++-- xeth/xeth.go | 2 +- 7 files changed, 53 insertions(+), 31 deletions(-) diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 8099d4dc60..f28f33f3db 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -43,6 +43,7 @@ import ( "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/rpc/codec" "github.com/ethereum/go-ethereum/rpc/comms" + "github.com/ethereum/go-ethereum/trie" "github.com/mattn/go-colorable" "github.com/mattn/go-isatty" ) @@ -338,6 +339,10 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso func main() { runtime.GOMAXPROCS(runtime.NumCPU()) defer logger.Flush() + defer func() { + fmt.Println("written using the trie:", trie.Written, "bytes") + fmt.Println("written by the database:", ethdb.Written, "bytes") + }() if err := app.Run(os.Args); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) diff --git a/core/chain_manager.go b/core/chain_manager.go index 1a703d0840..d42cd8be04 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -73,9 +73,6 @@ type ChainManager struct { lastBlockHash common.Hash currentGasLimit *big.Int - transState *state.StateDB - txState *state.ManagedState - cache *lru.Cache // cache is the LRU caching futureBlocks *lru.Cache // future blocks are blocks added for later processing @@ -128,9 +125,7 @@ func NewChainManager(blockDb, stateDb, extraDb common.Database, pow pow.PoW, mux } } - bc.transState = bc.State().Copy() // Take ownership of this particular state - bc.txState = state.ManageState(bc.State().Copy()) bc.futureBlocks, _ = lru.New(maxFutureBlocks) bc.makeCache() @@ -152,9 +147,6 @@ func (bc *ChainManager) SetHead(head *types.Block) { bc.currentBlock = head bc.makeCache() - statedb := state.New(head.Root(), bc.stateDb) - bc.txState = state.ManageState(statedb) - bc.transState = statedb.Copy() bc.setTotalDifficulty(head.Td) bc.insert(head) bc.setLastState() @@ -203,17 +195,6 @@ func (self *ChainManager) State() *state.StateDB { return state.New(self.CurrentBlock().Root(), self.stateDb) } -func (self *ChainManager) TransState() *state.StateDB { - self.tsmu.RLock() - defer self.tsmu.RUnlock() - - return self.transState -} - -func (self *ChainManager) setTransState(statedb *state.StateDB) { - self.transState = statedb -} - func (bc *ChainManager) recover() bool { data, _ := bc.blockDb.Get([]byte("checkpoint")) if len(data) != 0 { @@ -529,9 +510,6 @@ func (self *ChainManager) WriteBlock(block *types.Block, queued bool) (status wr self.insert(block) self.mu.Unlock() - self.setTransState(state.New(block.Root(), self.stateDb)) - self.txState.SetState(state.New(block.Root(), self.stateDb)) - status = CanonStatTy } else { status = SideStatTy diff --git a/core/transaction_util.go b/core/transaction_util.go index 752d4f0880..60cbdc529a 100644 --- a/core/transaction_util.go +++ b/core/transaction_util.go @@ -19,9 +19,11 @@ package core import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/rlp" + "github.com/syndtr/goleveldb/leveldb" ) var ( @@ -31,13 +33,21 @@ var ( // PutTransactions stores the transactions in the given database func PutTransactions(db common.Database, block *types.Block, txs types.Transactions) { + batch := new(leveldb.Batch) + _, batchWrite := db.(*ethdb.LDBDatabase) + for i, tx := range block.Transactions() { rlpEnc, err := rlp.EncodeToBytes(tx) if err != nil { glog.V(logger.Debug).Infoln("Failed encoding tx", err) return } - db.Put(tx.Hash().Bytes(), rlpEnc) + + if batchWrite { + batch.Put(tx.Hash().Bytes(), rlpEnc) + } else { + db.Put(tx.Hash().Bytes(), rlpEnc) + } var txExtra struct { BlockHash common.Hash @@ -52,20 +62,44 @@ func PutTransactions(db common.Database, block *types.Block, txs types.Transacti glog.V(logger.Debug).Infoln("Failed encoding tx meta data", err) return } - db.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta) + + if batchWrite { + batch.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta) + } else { + db.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta) + } + } + + if db, ok := db.(*ethdb.LDBDatabase); ok { + if err := db.LDB().Write(batch, nil); err != nil { + glog.V(logger.Error).Infoln("db write err:", err) + } } } // PutReceipts stores the receipts in the current database func PutReceipts(db common.Database, receipts types.Receipts) error { + batch := new(leveldb.Batch) + _, batchWrite := db.(*ethdb.LDBDatabase) + for _, receipt := range receipts { storageReceipt := (*types.ReceiptForStorage)(receipt) bytes, err := rlp.EncodeToBytes(storageReceipt) if err != nil { return err } - err = db.Put(append(receiptsPre, receipt.TxHash[:]...), bytes) - if err != nil { + + if batchWrite { + batch.Put(append(receiptsPre, receipt.TxHash[:]...), bytes) + } else { + err = db.Put(append(receiptsPre, receipt.TxHash[:]...), bytes) + if err != nil { + return err + } + } + } + if db, ok := db.(*ethdb.LDBDatabase); ok { + if err := db.LDB().Write(batch, nil); err != nil { return err } } diff --git a/ethdb/database.go b/ethdb/database.go index c75136a1b9..25dba552a9 100644 --- a/ethdb/database.go +++ b/ethdb/database.go @@ -34,6 +34,8 @@ import ( gometrics "github.com/rcrowley/go-metrics" ) +var Written uint64 + var OpenFileLimit = 64 type LDBDatabase struct { @@ -59,7 +61,7 @@ type LDBDatabase struct { // when data needs to be stored and written to disk. func NewLDBDatabase(file string) (*LDBDatabase, error) { // Open the db - db, err := leveldb.OpenFile(file, &opt.Options{OpenFilesCacheCapacity: OpenFileLimit}) + db, err := leveldb.OpenFile(file, &opt.Options{OpenFilesCacheCapacity: OpenFileLimit, BlockSize: 1 * opt.KiB}) // check for corruption and attempt to recover if _, iscorrupted := err.(*errors.ErrCorrupted); iscorrupted { db, err = leveldb.RecoverFile(file, nil) @@ -76,6 +78,7 @@ func NewLDBDatabase(file string) (*LDBDatabase, error) { // Put puts the given key / value to the queue func (self *LDBDatabase) Put(key []byte, value []byte) error { + Written += uint64(len(value)) // Measure the database put latency, if requested if self.putTimer != nil { defer self.putTimer.UpdateSince(time.Now()) diff --git a/trie/hashnode.go b/trie/hashnode.go index a6ab084a89..49fcad44e1 100644 --- a/trie/hashnode.go +++ b/trie/hashnode.go @@ -42,5 +42,5 @@ func (self *HashNode) setDirty(dirty bool) { // These methods will never be called but we have to satisfy Node interface func (self *HashNode) Value() Node { return nil } -func (self *HashNode) Dirty() bool { return true } +func (self *HashNode) Dirty() bool { return false } func (self *HashNode) Copy(t *Trie) Node { return NewHash(common.CopyBytes(self.key), t) } diff --git a/trie/trie.go b/trie/trie.go index 30c2569fa5..9b9f43f439 100644 --- a/trie/trie.go +++ b/trie/trie.go @@ -27,6 +27,8 @@ import ( "github.com/ethereum/go-ethereum/crypto" ) +var Written uint64 + func ParanoiaCheck(t1 *Trie, backend Backend) (bool, *Trie) { t2 := New(nil, backend) @@ -373,9 +375,9 @@ func (self *Trie) store(node Node) interface{} { if len(data) >= 32 { key := crypto.Sha3(data) if node.Dirty() { - //fmt.Println("save", node) - //fmt.Println() + Written += uint64(len(data)) self.cache.Put(key, data) + node.setDirty(false) } return key diff --git a/xeth/xeth.go b/xeth/xeth.go index 19d9c0ad46..6f8604bb4f 100644 --- a/xeth/xeth.go +++ b/xeth/xeth.go @@ -123,7 +123,7 @@ func New(ethereum *eth.Ethereum, frontend Frontend) *XEth { if frontend == nil { xeth.frontend = dummyFrontend{} } - xeth.state = NewState(xeth, xeth.backend.ChainManager().TransState()) + xeth.state = NewState(xeth, xeth.backend.ChainManager().State()) go xeth.start() go xeth.filterManager.Start()