good morning!!!!
Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
B
bor
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container registry
Harbor Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
open
bor
Commits
4a4abc41
Unverified
Commit
4a4abc41
authored
Nov 22, 2018
by
Péter Szilágyi
Browse files
Options
Downloads
Patches
Plain Diff
trie: approximate the wasted cache metaspace closer
parent
1528b791
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
trie/database.go
+44
-14
44 additions, 14 deletions
trie/database.go
with
44 additions
and
14 deletions
trie/database.go
+
44
−
14
View file @
4a4abc41
...
@@ -21,6 +21,7 @@ import (
...
@@ -21,6 +21,7 @@ import (
"errors"
"errors"
"fmt"
"fmt"
"io"
"io"
"reflect"
"sync"
"sync"
"time"
"time"
...
@@ -84,7 +85,8 @@ type Database struct {
...
@@ -84,7 +85,8 @@ type Database struct {
flushnodes
uint64
// Nodes flushed since last commit
flushnodes
uint64
// Nodes flushed since last commit
flushsize
common
.
StorageSize
// Data storage flushed since last commit
flushsize
common
.
StorageSize
// Data storage flushed since last commit
dirtiesSize
common
.
StorageSize
// Storage size of the dirty node cache (exc. flushlist)
dirtiesSize
common
.
StorageSize
// Storage size of the dirty node cache (exc. metadata)
childrenSize
common
.
StorageSize
// Storage size of the external children tracking
preimagesSize
common
.
StorageSize
// Storage size of the preimages cache
preimagesSize
common
.
StorageSize
// Storage size of the preimages cache
lock
sync
.
RWMutex
lock
sync
.
RWMutex
...
@@ -146,6 +148,15 @@ type cachedNode struct {
...
@@ -146,6 +148,15 @@ type cachedNode struct {
flushNext
common
.
Hash
// Next node in the flush-list
flushNext
common
.
Hash
// Next node in the flush-list
}
}
// cachedNodeSize is the raw size of a cachedNode data structure without any
// node data included. It's an approximate size, but should be a lot better
// than not counting them.
var
cachedNodeSize
=
int
(
reflect
.
TypeOf
(
cachedNode
{})
.
Size
())
// cachedNodeChildrenSize is the raw size of an initialized but empty external
// reference map.
const
cachedNodeChildrenSize
=
48
// rlp returns the raw rlp encoded blob of the cached node, either directly from
// rlp returns the raw rlp encoded blob of the cached node, either directly from
// the cache, or by regenerating it from the collapsed node.
// the cache, or by regenerating it from the collapsed node.
func
(
n
*
cachedNode
)
rlp
()
[]
byte
{
func
(
n
*
cachedNode
)
rlp
()
[]
byte
{
...
@@ -302,7 +313,9 @@ func NewDatabaseWithCache(diskdb ethdb.KeyValueStore, cache int) *Database {
...
@@ -302,7 +313,9 @@ func NewDatabaseWithCache(diskdb ethdb.KeyValueStore, cache int) *Database {
return
&
Database
{
return
&
Database
{
diskdb
:
diskdb
,
diskdb
:
diskdb
,
cleans
:
cleans
,
cleans
:
cleans
,
dirties
:
map
[
common
.
Hash
]
*
cachedNode
{{}
:
{}},
dirties
:
map
[
common
.
Hash
]
*
cachedNode
{{}
:
{
children
:
make
(
map
[
common
.
Hash
]
uint16
),
}},
preimages
:
make
(
map
[
common
.
Hash
][]
byte
),
preimages
:
make
(
map
[
common
.
Hash
][]
byte
),
}
}
}
}
...
@@ -491,11 +504,15 @@ func (db *Database) reference(child common.Hash, parent common.Hash) {
...
@@ -491,11 +504,15 @@ func (db *Database) reference(child common.Hash, parent common.Hash) {
// If the reference already exists, only duplicate for roots
// If the reference already exists, only duplicate for roots
if
db
.
dirties
[
parent
]
.
children
==
nil
{
if
db
.
dirties
[
parent
]
.
children
==
nil
{
db
.
dirties
[
parent
]
.
children
=
make
(
map
[
common
.
Hash
]
uint16
)
db
.
dirties
[
parent
]
.
children
=
make
(
map
[
common
.
Hash
]
uint16
)
db
.
childrenSize
+=
cachedNodeChildrenSize
}
else
if
_
,
ok
=
db
.
dirties
[
parent
]
.
children
[
child
];
ok
&&
parent
!=
(
common
.
Hash
{})
{
}
else
if
_
,
ok
=
db
.
dirties
[
parent
]
.
children
[
child
];
ok
&&
parent
!=
(
common
.
Hash
{})
{
return
return
}
}
node
.
parents
++
node
.
parents
++
db
.
dirties
[
parent
]
.
children
[
child
]
++
db
.
dirties
[
parent
]
.
children
[
child
]
++
if
db
.
dirties
[
parent
]
.
children
[
child
]
==
1
{
db
.
childrenSize
+=
common
.
HashLength
+
2
// uint16 counter
}
}
}
// Dereference removes an existing reference from a root node.
// Dereference removes an existing reference from a root node.
...
@@ -532,6 +549,7 @@ func (db *Database) dereference(child common.Hash, parent common.Hash) {
...
@@ -532,6 +549,7 @@ func (db *Database) dereference(child common.Hash, parent common.Hash) {
node
.
children
[
child
]
--
node
.
children
[
child
]
--
if
node
.
children
[
child
]
==
0
{
if
node
.
children
[
child
]
==
0
{
delete
(
node
.
children
,
child
)
delete
(
node
.
children
,
child
)
db
.
childrenSize
-=
(
common
.
HashLength
+
2
)
// uint16 counter
}
}
}
}
// If the child does not exist, it's a previously committed node.
// If the child does not exist, it's a previously committed node.
...
@@ -566,6 +584,9 @@ func (db *Database) dereference(child common.Hash, parent common.Hash) {
...
@@ -566,6 +584,9 @@ func (db *Database) dereference(child common.Hash, parent common.Hash) {
}
}
delete
(
db
.
dirties
,
child
)
delete
(
db
.
dirties
,
child
)
db
.
dirtiesSize
-=
common
.
StorageSize
(
common
.
HashLength
+
int
(
node
.
size
))
db
.
dirtiesSize
-=
common
.
StorageSize
(
common
.
HashLength
+
int
(
node
.
size
))
if
node
.
children
!=
nil
{
db
.
childrenSize
-=
cachedNodeChildrenSize
}
}
}
}
}
...
@@ -584,8 +605,9 @@ func (db *Database) Cap(limit common.StorageSize) error {
...
@@ -584,8 +605,9 @@ func (db *Database) Cap(limit common.StorageSize) error {
// db.dirtiesSize only contains the useful data in the cache, but when reporting
// db.dirtiesSize only contains the useful data in the cache, but when reporting
// the total memory consumption, the maintenance metadata is also needed to be
// the total memory consumption, the maintenance metadata is also needed to be
// counted. For every useful node, we track 2 extra hashes as the flushlist.
// counted.
size
:=
db
.
dirtiesSize
+
common
.
StorageSize
((
len
(
db
.
dirties
)
-
1
)
*
2
*
common
.
HashLength
)
size
:=
db
.
dirtiesSize
+
common
.
StorageSize
((
len
(
db
.
dirties
)
-
1
)
*
cachedNodeSize
)
size
+=
db
.
childrenSize
-
common
.
StorageSize
(
len
(
db
.
dirties
[
common
.
Hash
{}]
.
children
)
*
(
common
.
HashLength
+
2
))
// If the preimage cache got large enough, push to disk. If it's still small
// If the preimage cache got large enough, push to disk. If it's still small
// leave for later to deduplicate writes.
// leave for later to deduplicate writes.
...
@@ -621,10 +643,12 @@ func (db *Database) Cap(limit common.StorageSize) error {
...
@@ -621,10 +643,12 @@ func (db *Database) Cap(limit common.StorageSize) error {
batch
.
Reset
()
batch
.
Reset
()
}
}
// Iterate to the next flush item, or abort if the size cap was achieved. Size
// Iterate to the next flush item, or abort if the size cap was achieved. Size
// is the total size, including both the useful cached data (hash -> blob), as
// is the total size, including the useful cached data (hash -> blob), the
// well as the flushlist metadata (2*hash). When flushing items from the cache,
// cache item metadata, as well as external children mappings.
// we need to reduce both.
size
-=
common
.
StorageSize
(
common
.
HashLength
+
int
(
node
.
size
)
+
cachedNodeSize
)
size
-=
common
.
StorageSize
(
3
*
common
.
HashLength
+
int
(
node
.
size
))
if
node
.
children
!=
nil
{
size
-=
common
.
StorageSize
(
cachedNodeChildrenSize
+
len
(
node
.
children
)
*
(
common
.
HashLength
+
2
))
}
oldest
=
node
.
flushNext
oldest
=
node
.
flushNext
}
}
// Flush out any remainder data from the last batch
// Flush out any remainder data from the last batch
...
@@ -646,6 +670,9 @@ func (db *Database) Cap(limit common.StorageSize) error {
...
@@ -646,6 +670,9 @@ func (db *Database) Cap(limit common.StorageSize) error {
db
.
oldest
=
node
.
flushNext
db
.
oldest
=
node
.
flushNext
db
.
dirtiesSize
-=
common
.
StorageSize
(
common
.
HashLength
+
int
(
node
.
size
))
db
.
dirtiesSize
-=
common
.
StorageSize
(
common
.
HashLength
+
int
(
node
.
size
))
if
node
.
children
!=
nil
{
db
.
childrenSize
-=
common
.
StorageSize
(
cachedNodeChildrenSize
+
len
(
node
.
children
)
*
(
common
.
HashLength
+
2
))
}
}
}
if
db
.
oldest
!=
(
common
.
Hash
{})
{
if
db
.
oldest
!=
(
common
.
Hash
{})
{
db
.
dirties
[
db
.
oldest
]
.
flushPrev
=
common
.
Hash
{}
db
.
dirties
[
db
.
oldest
]
.
flushPrev
=
common
.
Hash
{}
...
@@ -803,7 +830,9 @@ func (c *cleaner) Put(key []byte, rlp []byte) error {
...
@@ -803,7 +830,9 @@ func (c *cleaner) Put(key []byte, rlp []byte) error {
// Remove the node from the dirty cache
// Remove the node from the dirty cache
delete
(
c
.
db
.
dirties
,
hash
)
delete
(
c
.
db
.
dirties
,
hash
)
c
.
db
.
dirtiesSize
-=
common
.
StorageSize
(
common
.
HashLength
+
int
(
node
.
size
))
c
.
db
.
dirtiesSize
-=
common
.
StorageSize
(
common
.
HashLength
+
int
(
node
.
size
))
if
node
.
children
!=
nil
{
c
.
db
.
dirtiesSize
-=
common
.
StorageSize
(
cachedNodeChildrenSize
+
len
(
node
.
children
)
*
(
common
.
HashLength
+
2
))
}
// Move the flushed node into the clean cache to prevent insta-reloads
// Move the flushed node into the clean cache to prevent insta-reloads
if
c
.
db
.
cleans
!=
nil
{
if
c
.
db
.
cleans
!=
nil
{
c
.
db
.
cleans
.
Set
(
string
(
hash
[
:
]),
rlp
)
c
.
db
.
cleans
.
Set
(
string
(
hash
[
:
]),
rlp
)
...
@@ -823,9 +852,10 @@ func (db *Database) Size() (common.StorageSize, common.StorageSize) {
...
@@ -823,9 +852,10 @@ func (db *Database) Size() (common.StorageSize, common.StorageSize) {
// db.dirtiesSize only contains the useful data in the cache, but when reporting
// db.dirtiesSize only contains the useful data in the cache, but when reporting
// the total memory consumption, the maintenance metadata is also needed to be
// the total memory consumption, the maintenance metadata is also needed to be
// counted. For every useful node, we track 2 extra hashes as the flushlist.
// counted.
var
flushlistSize
=
common
.
StorageSize
((
len
(
db
.
dirties
)
-
1
)
*
2
*
common
.
HashLength
)
var
metadataSize
=
common
.
StorageSize
((
len
(
db
.
dirties
)
-
1
)
*
cachedNodeSize
)
return
db
.
dirtiesSize
+
flushlistSize
,
db
.
preimagesSize
var
metarootRefs
=
common
.
StorageSize
(
len
(
db
.
dirties
[
common
.
Hash
{}]
.
children
)
*
(
common
.
HashLength
+
2
))
return
db
.
dirtiesSize
+
db
.
childrenSize
+
metadataSize
-
metarootRefs
,
db
.
preimagesSize
}
}
// verifyIntegrity is a debug method to iterate over the entire trie stored in
// verifyIntegrity is a debug method to iterate over the entire trie stored in
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment