-
Notifications
You must be signed in to change notification settings - Fork 20.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
core,eth: add rpc method to trie flush frequency #24785
Conversation
core/blockchain.go
Outdated
if mode := atomic.LoadInt32(&bc.gcmode); mode == archiveMode { | ||
return triedb.Commit(root, false, nil) | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The upper clause return
s, let's get rid of the else
and unindent the next clause
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And after that, maybe
if current := block.NumberU64(); current <= TriesInMemory {
return nil
}
And we can un-indent some more
Good start, but this way we'll only be able to toggle archive on or off. I think it would be neat to set it to a more linear value. So by default, we have it set to "2 hours of block processing". Which is a nice UX. However, I'd like to be able to say "I want to always flush after 1024 blocks" or something like that, because then I know what the max For that to happen,
needs to be modified to something like
(and also possibly verifying so we don't wrap around on negatives or whatever) |
What about replacing Edit: |
I think it's nice to have both. Setting |
I combined
|
core/blockchain.go
Outdated
snaps *snapshot.Tree // Snapshot tree for fast trie leaf access | ||
triegc *prque.Prque // Priority queue mapping block numbers to tries to gc | ||
gcproc time.Duration // Accumulates canonical block processing for trie dumping | ||
sinceFlush uint32 // Accumulates number of canonical blocks since last trie flush |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this have to be a member on Blockchain? It can be just a variable inside that loop, no?
core/blockchain.go
Outdated
@@ -1250,6 +1262,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types. | |||
triedb.Commit(header.Root, true, nil) | |||
lastWrite = chosen | |||
bc.gcproc = 0 | |||
bc.sinceFlush = 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you really need both sinceFlush
and lastWrite
? Isn't sinceFlush
derivable from lastWrite
?
eth/api.go
Outdated
@@ -607,3 +607,13 @@ func (api *PrivateDebugAPI) GetAccessibleState(from, to rpc.BlockNumber) (uint64 | |||
} | |||
return 0, fmt.Errorf("No state found") | |||
} | |||
|
|||
type gcPolicy struct { | |||
Archive bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's nice to surface this to the user, so he/she can set { "archive"=true}
, but not so nice to just ignore archive and only care about FlushFrequency it later on
Back to you, @s1na :) |
@s1na please don't forget about this one, it would be nice to have in several situations |
^^ 🥺 |
@holiman very sorry I've been putting this off. I'm gonna get started on it asap. |
It seems |
I've rebased the PR and updated it so that you can configure it with block processing time. Now running it on a node for testing. |
For the normal case: INFO [12-08|08:33:13.133] Deciding to flush interval=1h0m0s chosen=16,138,695 time=10m46.357989217s lastWrite=0
INFO [12-08|08:33:13.149] Imported new potential chain segment number=16,138,823 hash=9008c1..260763 blocks=1 txs=143 mgas=12.913 elapsed=103.009ms mgasps=125.36
2 dirty=1021.78MiB
// Now call debug.setTrieFlushInterval('10m47s')
// Ok interval updated
INFO [12-08|08:33:25.016] Deciding to flush interval=10m47s chosen=16,138,696 time=10m46.421472469s lastWrite=0
INFO [12-08|08:33:25.028] Imported new potential chain segment number=16,138,824 hash=5aba19..72d9e8 blocks=1 txs=113 mgas=10.422 elapsed=125.296ms mgasps=83.178
dirty=1022.18MiB
// Here it went over the interval and flushed
INFO [12-08|08:34:36.568] Deciding to flush interval=10m47s chosen=16,138,702 time=10m47.175393223s lastWrite=0
INFO [12-08|08:34:59.657] Persisted trie from memory database nodes=3,859,148 size=910.81MiB time=32.773272419s gcnodes=7,785,269 gcsize=3.15GiB gctime=37.463748875s livenodes=496,459 livesize=179.47MiB
INFO [12-08|08:34:59.657] Imported new potential chain segment number=16,138,830 hash=ec63f0..8ebb58 blocks=1 txs=112 mgas=29.195 elapsed=23.345s mgasps=1.251 dirty=225.66MiB
// And we see time was reset and lastWrite now indicates the correct block
INFO [12-08|08:35:04.063] Deciding to flush interval=10m47s chosen=16,138,703 time=154.97035ms lastWrite=16,138,702
INFO [12-08|08:35:04.065] Imported new potential chain segment number=16,138,831 hash=0be578..f9b398 blocks=1 txs=100 mgas=9.205 elapsed=520.668ms mgasps=17.679 dirty=226.68MiB |
I find it hard to choose a good parameter value to target a specific flushing interval since there's quite a bit of variance in block processing times and the accumulated time being different from actual wall clock. However it's good if all you care about is relativity. I.e. if you know the default is |
Well, the parameters to target is |
flushInterval := time.Duration(atomic.LoadInt64(&bc.flushInterval)) | ||
// If we exceeded time allowance, flush an entire trie to disk | ||
if bc.gcproc > flushInterval { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The diff is large mainly due to un-indenting an if-clause (which is good). But just to verify: this change right here is the only real diff, and the heart of the change, right?
We compare the gcproc
with the configurable flushInterval
instead of cacheConfig.TrieTimeLimit
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes see this commit: bea73e5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Yes but if I set it to |
No, it will take one hour. AS in
You are right that
But other than that, isn't it kind of "the most UX friendly of two bad options" ? |
Ah I did notice that when node is stopped and restarted the processing time goes by quicker. Right, I see the other option isn't so much better. I think the PR is ready. |
…ency (ethereum#24785) This PR makes it possible to modify the flush interval time via RPC. On one extreme, `0s`, it would act as an archive node. If set to `1h`, means that after one hour of effective block processing time, the trie would be flushed. If one block takes 200ms, this means that a flush would occur every `5*3600=18000` blocks -- however, if the memory size of the cached states grows too large, it will flush sooner. Essentially, this makes it possible to configure the node to be more or less "archive:ish", and without restarting the node while reconfiguring it.
See #24720