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
deee9cb1
Commit
deee9cb1
authored
Mar 20, 2015
by
obscuren
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added caching for block chain. Currently set to 10k
parent
01ff0b31
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
136 additions
and
2 deletions
+136
-2
block_cache.go
core/block_cache.go
+68
-0
block_cache_test.go
core/block_cache_test.go
+48
-0
chain_manager.go
core/chain_manager.go
+19
-1
chain_manager_test.go
core/chain_manager_test.go
+1
-1
No files found.
core/block_cache.go
0 → 100644
View file @
deee9cb1
package
core
import
(
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// BlockCache implements a caching mechanism specifically for blocks and uses FILO to pop
type
BlockCache
struct
{
size
int
hashes
[]
common
.
Hash
blocks
map
[
common
.
Hash
]
*
types
.
Block
mu
sync
.
RWMutex
}
// Creates and returns a `BlockCache` with `size`. If `size` is smaller than 1 it will panic
func
NewBlockCache
(
size
int
)
*
BlockCache
{
if
size
<
1
{
panic
(
"block cache size not allowed to be smaller than 1"
)
}
bc
:=
&
BlockCache
{
size
:
size
}
bc
.
Clear
()
return
bc
}
func
(
bc
*
BlockCache
)
Clear
()
{
bc
.
blocks
=
make
(
map
[
common
.
Hash
]
*
types
.
Block
)
bc
.
hashes
=
nil
}
func
(
bc
*
BlockCache
)
Push
(
block
*
types
.
Block
)
{
bc
.
mu
.
Lock
()
defer
bc
.
mu
.
Unlock
()
if
len
(
bc
.
hashes
)
==
bc
.
size
{
delete
(
bc
.
blocks
,
bc
.
hashes
[
0
])
// XXX There are a few other options on solving this
// 1) use a poller / GC like mechanism to clean up untracked objects
// 2) copy as below
// re-use the slice and remove the reference to bc.hashes[0]
// this will allow the element to be garbage collected.
copy
(
bc
.
hashes
,
bc
.
hashes
[
1
:
])
}
else
{
bc
.
hashes
=
append
(
bc
.
hashes
,
common
.
Hash
{})
}
hash
:=
block
.
Hash
()
bc
.
blocks
[
hash
]
=
block
bc
.
hashes
[
len
(
bc
.
hashes
)
-
1
]
=
hash
}
func
(
bc
*
BlockCache
)
Get
(
hash
common
.
Hash
)
*
types
.
Block
{
bc
.
mu
.
RLock
()
defer
bc
.
mu
.
RUnlock
()
if
block
,
haz
:=
bc
.
blocks
[
hash
];
haz
{
return
block
}
return
nil
}
core/block_cache_test.go
0 → 100644
View file @
deee9cb1
package
core
import
(
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
func
newChain
(
size
int
)
(
chain
[]
*
types
.
Block
)
{
var
parentHash
common
.
Hash
for
i
:=
0
;
i
<
size
;
i
++
{
block
:=
types
.
NewBlock
(
parentHash
,
common
.
Address
{},
common
.
Hash
{},
new
(
big
.
Int
),
0
,
""
)
block
.
Header
()
.
Number
=
big
.
NewInt
(
int64
(
i
))
chain
=
append
(
chain
,
block
)
parentHash
=
block
.
Hash
()
}
return
}
func
insertChainCache
(
cache
*
BlockCache
,
chain
[]
*
types
.
Block
)
{
for
_
,
block
:=
range
chain
{
cache
.
Push
(
block
)
}
}
func
TestNewBlockCache
(
t
*
testing
.
T
)
{
chain
:=
newChain
(
3
)
cache
:=
NewBlockCache
(
2
)
insertChainCache
(
cache
,
chain
)
if
cache
.
hashes
[
0
]
!=
chain
[
1
]
.
Hash
()
{
t
.
Error
(
"oldest block incorrect"
)
}
}
func
TestInclusion
(
t
*
testing
.
T
)
{
chain
:=
newChain
(
3
)
cache
:=
NewBlockCache
(
3
)
insertChainCache
(
cache
,
chain
)
for
_
,
block
:=
range
chain
{
if
b
:=
cache
.
Get
(
block
.
Hash
());
b
==
nil
{
t
.
Errorf
(
"getting %x failed"
,
block
.
Hash
())
}
}
}
core/chain_manager.go
View file @
deee9cb1
...
...
@@ -23,6 +23,8 @@ var (
blockNumPre
=
[]
byte
(
"block-num-"
)
)
const
blockCacheLimit
=
10000
type
StateQuery
interface
{
GetAccount
(
addr
[]
byte
)
*
state
.
StateObject
}
...
...
@@ -92,15 +94,25 @@ type ChainManager struct {
transState
*
state
.
StateDB
txState
*
state
.
ManagedState
cache
*
BlockCache
quit
chan
struct
{}
}
func
NewChainManager
(
blockDb
,
stateDb
common
.
Database
,
mux
*
event
.
TypeMux
)
*
ChainManager
{
bc
:=
&
ChainManager
{
blockDb
:
blockDb
,
stateDb
:
stateDb
,
genesisBlock
:
GenesisBlock
(
stateDb
),
eventMux
:
mux
,
quit
:
make
(
chan
struct
{})}
bc
:=
&
ChainManager
{
blockDb
:
blockDb
,
stateDb
:
stateDb
,
genesisBlock
:
GenesisBlock
(
stateDb
),
eventMux
:
mux
,
quit
:
make
(
chan
struct
{})
,
cache
:
NewBlockCache
(
blockCacheLimit
)
}
bc
.
setLastBlock
()
bc
.
transState
=
bc
.
State
()
.
Copy
()
// Take ownership of this particular state
bc
.
txState
=
state
.
ManageState
(
bc
.
State
()
.
Copy
())
// load in last `blockCacheLimit` - 1 blocks. Last block is the current.
ancestors
:=
bc
.
GetAncestors
(
bc
.
currentBlock
,
blockCacheLimit
-
1
)
ancestors
=
append
(
ancestors
,
bc
.
currentBlock
)
for
_
,
block
:=
range
ancestors
{
bc
.
cache
.
Push
(
block
)
}
go
bc
.
update
()
return
bc
...
...
@@ -275,6 +287,8 @@ func (bc *ChainManager) insert(block *types.Block) {
key
:=
append
(
blockNumPre
,
block
.
Number
()
.
Bytes
()
...
)
bc
.
blockDb
.
Put
(
key
,
bc
.
lastBlockHash
.
Bytes
())
// Push block to cache
bc
.
cache
.
Push
(
block
)
}
func
(
bc
*
ChainManager
)
write
(
block
*
types
.
Block
)
{
...
...
@@ -318,6 +332,10 @@ func (self *ChainManager) GetBlockHashesFromHash(hash common.Hash, max uint64) (
}
func
(
self
*
ChainManager
)
GetBlock
(
hash
common
.
Hash
)
*
types
.
Block
{
if
block
:=
self
.
cache
.
Get
(
hash
);
block
!=
nil
{
return
block
}
data
,
_
:=
self
.
blockDb
.
Get
(
append
(
blockHashPre
,
hash
[
:
]
...
))
if
len
(
data
)
==
0
{
return
nil
...
...
core/chain_manager_test.go
View file @
deee9cb1
...
...
@@ -69,7 +69,7 @@ func printChain(bc *ChainManager) {
func
testChain
(
chainB
types
.
Blocks
,
bman
*
BlockProcessor
)
(
*
big
.
Int
,
error
)
{
td
:=
new
(
big
.
Int
)
for
_
,
block
:=
range
chainB
{
td2
,
err
:=
bman
.
bc
.
processor
.
Process
(
block
)
td2
,
_
,
err
:=
bman
.
bc
.
processor
.
Process
(
block
)
if
err
!=
nil
{
if
IsKnownBlockErr
(
err
)
{
continue
...
...
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