-
Notifications
You must be signed in to change notification settings - Fork 471
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
320 rounds: expose block header from txtail #3935
320 rounds: expose block header from txtail #3935
Conversation
algorandskiy
commented
Apr 28, 2022
•
edited
Loading
edited
- Make block header accessible from txtail with BlockHdrCached method
- Some fixes to in-memory data representation
- Added new consensus parameter to increase blocks lookback size
- More comments and test
cd15861
to
e9605d3
Compare
e9605d3
to
cf0528c
Compare
cf0528c
to
13570b7
Compare
299b79b
to
bed45ba
Compare
ledger/txtail.go
Outdated
@@ -207,17 +229,26 @@ func (t *txTail) committedUpTo(rnd basics.Round) (retRound, lookback basics.Roun | |||
delete(t.lastValid, t.lowWaterMark) | |||
} | |||
|
|||
return (rnd + 1).SubSaturate(maxlife), basics.Round(0) | |||
deeperHistory := basics.Round(t.recent[rnd].proto.DeeperBlockHeaderHistory) |
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.
Should we consider removing proto from roundLeases now and switching to t.blockHeaderData[rnd]? Now we have two consensus versions/protos in the txtail row?
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.
Okay, I tried this. Using t.blockHeaderData
instead of t.recent
requires taking a t.tailMu
lock (t.blockHeaderData
is changed in commitRound and Co and the race detector complains). t.recent
is updated in newBlock
and protected by l.trackerMu
in ledger.
For some reason the old l.trackerMu
lock does not lead to a horrible performance degradation as t.tailMu
does. I need to look further, leaving as is now.
ledger/txtail.go
Outdated
bufIdx := 0 | ||
t.tailMu.RLock() | ||
lastOffset := offset + maxTxnLife | ||
lastOffset := offset + retianSize - 1 |
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.
check -1
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 loop below is supposed to fill retainSize
elements starting from offset
, this means it should make retainSize
iterations and lastOffset
is exclusive => size of the interval [offset, lastOffset) is lastOffset - offset = retainSize
. Fixed
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.
Leaving some comments. Will continue review tomorrow.
// and valid if txn.LastValid - txn.FirstValid <= MaxTxnLife | ||
// the deepest lookup happens when txn.LastValid == current => txn.LastValid == Lastest + 1 | ||
// that gives Lastest + 1 - (MaxTxnLife + 1) = Lastest - MaxTxnLife as the first round to be accessible. | ||
func (l *Ledger) BlockHdrCached(rnd basics.Round) (bookkeeping.BlockHeader, error) { |
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.
Why not use this cache in BlockHdr()
instead of making a new function?
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 problem with differect code paths that call BlockHdr and eventually deadlock the tracker in initialization (namely ledger.(*accountUpdates).initializeFromDisk
called from reloadLedger
needs calls BlockHdr
with trackers lock taken.
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.
This requires deeper rework and getting rid of tr.mu or trackerMu mutexes.
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.
Hm, it's strange that locks are needed at all during initialization.
Codecov Report
@@ Coverage Diff @@
## feature/320-rounds #3935 +/- ##
======================================================
+ Coverage 50.13% 50.19% +0.06%
======================================================
Files 412 412
Lines 70683 70701 +18
======================================================
+ Hits 35434 35488 +54
+ Misses 31384 31352 -32
+ Partials 3865 3861 -4
Continue to review full report at Codecov.
|
// and valid if txn.LastValid - txn.FirstValid <= MaxTxnLife | ||
// the deepest lookup happens when txn.LastValid == current => txn.LastValid == Lastest + 1 | ||
// that gives Lastest + 1 - (MaxTxnLife + 1) = Lastest - MaxTxnLife as the first round to be accessible. | ||
func (l *Ledger) BlockHdrCached(rnd basics.Round) (bookkeeping.BlockHeader, error) { |
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.
Hm, it's strange that locks are needed at all during initialization.
// The first entry matches that current tracker database round - MaxTxnLife (tail size is MaxTxnLife + DeeperBlockHeaderHistory) | ||
// the second to tracker database round - (MaxTxnLife - 1), and so forth, and the last element is for the latest round. | ||
// Deltas are in-memory not-committed-yet data. | ||
blockHeaderData map[basics.Round]bookkeeping.BlockHeader |
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.
why is it a map and not an array like other fields?
ledger/txtail.go
Outdated
// preserve data for MaxTxnLife + DeeperBlockHeaderHistory | ||
proto := config.Consensus[t.blockHeaderData[rnd].CurrentProtocol] | ||
retainSize := proto.MaxTxnLife + proto.DeeperBlockHeaderHistory | ||
newLowestRound := rnd.SubSaturate(basics.Round(retainSize)) + 1 |
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.
newLowestRound := rnd.SubSaturate(basics.Round(retainSize)) + 1 | |
newLowestRound := rnd.SubSaturate(basics.Round(retainSize) + 1) |
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.
no. say newBase = 10 and retain size is 3. Then the map should have 8, 9, 10 and newLowestRound = 8.
so newLowestRound = 10 - 3 + 1 = 8.
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.
Sorry, I meant newLowestRound := rnd.SubSaturate(basics.Round(retainSize) - 1)
. The reason is that we don't want to remove round 0 when we shouldn't.
Alternatively:
newLowestRound := 0
if rnd + 1 > retainSize {
newLowestRound = rnd + 1 - retainSize
}
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.
this makes sense, thank you for noticing.
ledger/txtail.go
Outdated
proto := config.Consensus[t.blockHeaderData[rnd].CurrentProtocol] | ||
retainSize := proto.MaxTxnLife + proto.DeeperBlockHeaderHistory | ||
newLowestRound := rnd.SubSaturate(basics.Round(retainSize)) + 1 | ||
if newLowestRound > 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.
this check seems unnecessary
ledger/txtail.go
Outdated
proto := config.Consensus[t.blockHeaderData[rnd].CurrentProtocol] | ||
retainSize := proto.MaxTxnLife + proto.DeeperBlockHeaderHistory | ||
newLowestRound := rnd.SubSaturate(basics.Round(retainSize)) + 1 | ||
if newLowestRound > 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.
if newLowestRound > 0 { | |
if newLowestRound > t.lowestBlockHeaderRound |
otherwise increase in MaxTxnLife
or DeeperBlockHeaderHistory
can decrease t.lowestBlockHeaderRound
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.
right
newDeltaLength := len(t.roundTailSerializedDeltas) | ||
firstTailIdx := len(t.roundTailHashes) - newDeltaLength - int(retainSize) | ||
if firstTailIdx > 0 { | ||
t.roundTailHashes = t.roundTailHashes[firstTailIdx:] |
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.
can't we just remove the first newLowestRound - t.lowestBlockHeaderRound
elements similar to above?
A thought: could we make |