Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
4460dc9d
Commit
4460dc9d
authored
Jun 19, 2015
by
obscuren
Committed by
Jeffrey Wilcke
Jun 29, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core: added LRU caching and added batch writing when LDB is used
parent
2a5a55ef
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
81 additions
and
21 deletions
+81
-21
chain_manager.go
core/chain_manager.go
+81
-21
No files found.
core/chain_manager.go
View file @
4460dc9d
...
@@ -11,15 +11,18 @@ import (
...
@@ -11,15 +11,18 @@ import (
"time"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/compression/rle"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rlp"
"github.com/rcrowley/go-metrics"
"github.com/golang/groupcache/lru"
"github.com/syndtr/goleveldb/leveldb"
)
)
var
(
var
(
...
@@ -105,8 +108,9 @@ type ChainManager struct {
...
@@ -105,8 +108,9 @@ type ChainManager struct {
transState
*
state
.
StateDB
transState
*
state
.
StateDB
txState
*
state
.
ManagedState
txState
*
state
.
ManagedState
cache
*
BlockCache
cache
*
lru
.
Cache
// cache is the LRU caching
futureBlocks
*
BlockCache
futureBlocks
*
BlockCache
// future blocks are blocks added for later processing
nextBlocks
*
BlockCache
// next blocks is used during large inserts
quit
chan
struct
{}
quit
chan
struct
{}
// procInterrupt must be atomically called
// procInterrupt must be atomically called
...
@@ -123,7 +127,7 @@ func NewChainManager(genesis *types.Block, blockDb, stateDb common.Database, pow
...
@@ -123,7 +127,7 @@ func NewChainManager(genesis *types.Block, blockDb, stateDb common.Database, pow
genesisBlock
:
GenesisBlock
(
42
,
stateDb
),
genesisBlock
:
GenesisBlock
(
42
,
stateDb
),
eventMux
:
mux
,
eventMux
:
mux
,
quit
:
make
(
chan
struct
{}),
quit
:
make
(
chan
struct
{}),
cache
:
NewBlockCache
(
blockCacheLimit
),
cache
:
lru
.
New
(
blockCacheLimit
),
pow
:
pow
,
pow
:
pow
,
}
}
// Check the genesis block given to the chain manager. If the genesis block mismatches block number 0
// Check the genesis block given to the chain manager. If the genesis block mismatches block number 0
...
@@ -168,7 +172,7 @@ func (bc *ChainManager) SetHead(head *types.Block) {
...
@@ -168,7 +172,7 @@ func (bc *ChainManager) SetHead(head *types.Block) {
bc
.
removeBlock
(
block
)
bc
.
removeBlock
(
block
)
}
}
bc
.
cache
=
NewBlockCache
(
blockCacheLimit
)
bc
.
cache
=
lru
.
New
(
blockCacheLimit
)
bc
.
currentBlock
=
head
bc
.
currentBlock
=
head
bc
.
makeCache
()
bc
.
makeCache
()
...
@@ -257,11 +261,13 @@ func (bc *ChainManager) setLastState() {
...
@@ -257,11 +261,13 @@ func (bc *ChainManager) setLastState() {
func
(
bc
*
ChainManager
)
makeCache
()
{
func
(
bc
*
ChainManager
)
makeCache
()
{
if
bc
.
cache
==
nil
{
if
bc
.
cache
==
nil
{
bc
.
cache
=
NewBlockCache
(
blockCacheLimit
)
bc
.
cache
=
lru
.
New
(
blockCacheLimit
)
}
}
// load in last `blockCacheLimit` - 1 blocks. Last block is the current.
// load in last `blockCacheLimit` - 1 blocks. Last block is the current.
for
_
,
block
:=
range
bc
.
GetBlocksFromHash
(
bc
.
currentBlock
.
Hash
(),
blockCacheLimit
)
{
ancestors
:=
bc
.
GetAncestors
(
bc
.
currentBlock
,
blockCacheLimit
-
1
)
bc
.
cache
.
Push
(
block
)
ancestors
=
append
(
ancestors
,
bc
.
currentBlock
)
for
_
,
block
:=
range
ancestors
{
bc
.
cache
.
Add
(
block
.
Hash
(),
block
)
}
}
}
}
...
@@ -274,7 +280,7 @@ func (bc *ChainManager) Reset() {
...
@@ -274,7 +280,7 @@ func (bc *ChainManager) Reset() {
}
}
if
bc
.
cache
==
nil
{
if
bc
.
cache
==
nil
{
bc
.
cache
=
NewBlockCache
(
blockCacheLimit
)
bc
.
cache
=
lru
.
New
(
blockCacheLimit
)
}
}
// Prepare the genesis block
// Prepare the genesis block
...
@@ -359,15 +365,20 @@ func (bc *ChainManager) insert(block *types.Block) {
...
@@ -359,15 +365,20 @@ func (bc *ChainManager) insert(block *types.Block) {
}
}
func
(
bc
*
ChainManager
)
write
(
block
*
types
.
Block
)
{
func
(
bc
*
ChainManager
)
write
(
block
*
types
.
Block
)
{
enc
,
_
:=
rlp
.
EncodeToBytes
((
*
types
.
StorageBlock
)(
block
))
tstart
:=
time
.
Now
()
key
:=
append
(
blockHashPre
,
block
.
Hash
()
.
Bytes
()
...
)
err
:=
bc
.
blockDb
.
Put
(
key
,
enc
)
go
func
()
{
if
err
!=
nil
{
enc
,
_
:=
rlp
.
EncodeToBytes
((
*
types
.
StorageBlock
)(
block
))
glog
.
Fatal
(
"db write fail:"
,
err
)
key
:=
append
(
blockHashPre
,
block
.
Hash
()
.
Bytes
()
...
)
}
err
:=
bc
.
blockDb
.
Put
(
key
,
enc
)
if
err
!=
nil
{
glog
.
Fatal
(
"db write fail:"
,
err
)
}
}()
// Push block to cache
if
glog
.
V
(
logger
.
Debug
)
{
bc
.
cache
.
Push
(
block
)
glog
.
Infof
(
"wrote block #%v %s. Took %v
\n
"
,
block
.
Number
(),
common
.
PP
(
block
.
Hash
()
.
Bytes
()),
time
.
Since
(
tstart
))
}
}
}
// Accessors
// Accessors
...
@@ -377,6 +388,16 @@ func (bc *ChainManager) Genesis() *types.Block {
...
@@ -377,6 +388,16 @@ func (bc *ChainManager) Genesis() *types.Block {
// Block fetching methods
// Block fetching methods
func
(
bc
*
ChainManager
)
HasBlock
(
hash
common
.
Hash
)
bool
{
func
(
bc
*
ChainManager
)
HasBlock
(
hash
common
.
Hash
)
bool
{
if
bc
.
cache
.
Contains
(
hash
)
{
return
true
}
if
bc
.
nextBlocks
!=
nil
{
if
block
:=
bc
.
nextBlocks
.
Get
(
hash
);
block
!=
nil
{
return
true
}
}
data
,
_
:=
bc
.
blockDb
.
Get
(
append
(
blockHashPre
,
hash
[
:
]
...
))
data
,
_
:=
bc
.
blockDb
.
Get
(
append
(
blockHashPre
,
hash
[
:
]
...
))
return
len
(
data
)
!=
0
return
len
(
data
)
!=
0
}
}
...
@@ -403,11 +424,15 @@ func (self *ChainManager) GetBlockHashesFromHash(hash common.Hash, max uint64) (
...
@@ -403,11 +424,15 @@ func (self *ChainManager) GetBlockHashesFromHash(hash common.Hash, max uint64) (
}
}
func
(
self
*
ChainManager
)
GetBlock
(
hash
common
.
Hash
)
*
types
.
Block
{
func
(
self
*
ChainManager
)
GetBlock
(
hash
common
.
Hash
)
*
types
.
Block
{
/*
if
block
,
ok
:=
self
.
cache
.
Get
(
hash
);
ok
{
if block := self.cache.Get(hash); block != nil {
return
block
.
(
*
types
.
Block
)
}
if
self
.
nextBlocks
!=
nil
{
if
block
:=
self
.
nextBlocks
.
Get
(
hash
);
block
!=
nil
{
return
block
return
block
}
}
*/
}
data
,
_
:=
self
.
blockDb
.
Get
(
append
(
blockHashPre
,
hash
[
:
]
...
))
data
,
_
:=
self
.
blockDb
.
Get
(
append
(
blockHashPre
,
hash
[
:
]
...
))
if
len
(
data
)
==
0
{
if
len
(
data
)
==
0
{
...
@@ -418,6 +443,10 @@ func (self *ChainManager) GetBlock(hash common.Hash) *types.Block {
...
@@ -418,6 +443,10 @@ func (self *ChainManager) GetBlock(hash common.Hash) *types.Block {
glog
.
V
(
logger
.
Error
)
.
Infof
(
"invalid block RLP for hash %x: %v"
,
hash
,
err
)
glog
.
V
(
logger
.
Error
)
.
Infof
(
"invalid block RLP for hash %x: %v"
,
hash
,
err
)
return
nil
return
nil
}
}
// Add the block to the cache
self
.
cache
.
Add
(
hash
,
(
*
types
.
Block
)(
&
block
))
return
(
*
types
.
Block
)(
&
block
)
return
(
*
types
.
Block
)(
&
block
)
}
}
...
@@ -494,6 +523,31 @@ func (self *ChainManager) procFutureBlocks() {
...
@@ -494,6 +523,31 @@ func (self *ChainManager) procFutureBlocks() {
}
}
}
}
func
(
self
*
ChainManager
)
enqueueForWrite
(
block
*
types
.
Block
)
{
self
.
nextBlocks
.
Push
(
block
)
}
func
(
self
*
ChainManager
)
flushQueuedBlocks
()
{
db
,
batchWrite
:=
self
.
blockDb
.
(
*
ethdb
.
LDBDatabase
)
batch
:=
new
(
leveldb
.
Batch
)
self
.
nextBlocks
.
Each
(
func
(
i
int
,
block
*
types
.
Block
)
{
enc
,
_
:=
rlp
.
EncodeToBytes
((
*
types
.
StorageBlock
)(
block
))
key
:=
append
(
blockHashPre
,
block
.
Hash
()
.
Bytes
()
...
)
if
batchWrite
{
batch
.
Put
(
key
,
rle
.
Compress
(
enc
))
}
else
{
self
.
blockDb
.
Put
(
key
,
enc
)
}
})
if
batchWrite
{
db
.
LDB
()
.
Write
(
batch
,
nil
)
}
// reset the next blocks cache
self
.
nextBlocks
=
nil
}
// InsertChain will attempt to insert the given chain in to the canonical chain or, otherwise, create a fork. It an error is returned
// InsertChain will attempt to insert the given chain in to the canonical chain or, otherwise, create a fork. It an error is returned
// it will return the index number of the failing block as well an error describing what went wrong (for possible errors see core/errors.go).
// it will return the index number of the failing block as well an error describing what went wrong (for possible errors see core/errors.go).
func
(
self
*
ChainManager
)
InsertChain
(
chain
types
.
Blocks
)
(
int
,
error
)
{
func
(
self
*
ChainManager
)
InsertChain
(
chain
types
.
Blocks
)
(
int
,
error
)
{
...
@@ -503,6 +557,8 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
...
@@ -503,6 +557,8 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
self
.
chainmu
.
Lock
()
self
.
chainmu
.
Lock
()
defer
self
.
chainmu
.
Unlock
()
defer
self
.
chainmu
.
Unlock
()
self
.
nextBlocks
=
NewBlockCache
(
len
(
chain
))
// A queued approach to delivering events. This is generally
// A queued approach to delivering events. This is generally
// faster than direct delivery and requires much less mutex
// faster than direct delivery and requires much less mutex
// acquiring.
// acquiring.
...
@@ -520,6 +576,10 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
...
@@ -520,6 +576,10 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
// Start the parallel nonce verifier.
// Start the parallel nonce verifier.
go
verifyNonces
(
self
.
pow
,
chain
,
nonceQuit
,
nonceDone
)
go
verifyNonces
(
self
.
pow
,
chain
,
nonceQuit
,
nonceDone
)
defer
close
(
nonceQuit
)
defer
close
(
nonceQuit
)
defer
self
.
flushQueuedBlocks
()
defer
func
()
{
}()
txcount
:=
0
txcount
:=
0
for
i
,
block
:=
range
chain
{
for
i
,
block
:=
range
chain
{
...
@@ -632,7 +692,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
...
@@ -632,7 +692,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
}
}
// Write block to database. Eventually we'll have to improve on this and throw away blocks that are
// Write block to database. Eventually we'll have to improve on this and throw away blocks that are
// not in the canonical chain.
// not in the canonical chain.
self
.
w
rite
(
block
)
self
.
enqueueForW
rite
(
block
)
// Delete from future blocks
// Delete from future blocks
self
.
futureBlocks
.
Delete
(
block
.
Hash
())
self
.
futureBlocks
.
Delete
(
block
.
Hash
())
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment