-
Notifications
You must be signed in to change notification settings - Fork 223
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
Add support for multiple staging areas #1633
Conversation
Codecov Report
@@ Coverage Diff @@
## v0.10.0-dev #1633 +/- ##
===============================================
+ Coverage 59.95% 60.18% +0.23%
===============================================
Files 516 532 +16
Lines 20469 20673 +204
===============================================
+ Hits 12273 12443 +170
- Misses 6239 6267 +28
- Partials 1957 1963 +6
Continue to review full report at Codecov.
|
|
||
for _, shard := range sa.shards { | ||
if shard == nil { | ||
continue |
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 would a shard ever be nil
? Since this may hide bugs, I'd prefer it if you returned an error here.
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.
See response to next comment, it should explain this one as well.
|
||
// GetOrCreateShard attempts to retrieve a shard with the given name. | ||
// If it does not exist - a new shard is created using `createFunc`. | ||
func (sa *StagingArea) GetOrCreateShard(shardID StagingShardID, createFunc func() StagingShard) StagingShard { |
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.
Since GetOrCreateShard is only ever called from within a store, please consider passing a pointer to a store here instead of a shardID. This would:
a. Remove the need to maintain an IDs list
b. Disallow programmers from accessing shards they shouldn't have access to (e.g. in one store, another store's shard)
Of course, make sure that this does not harm performance.
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.
Please note sa.shards is an array.
This was done deliberately, because map access is much slower (I've tested this with integers, I'd expect the same to happen with pointers, because those are basically integers as well).
This, as you mentioned, has some worse properties, but using a map adds around 20~30 overhead for kaspad normal operation.
This also explains why in Commit a shard might be nil - we are going over all the array every time we Commit. Some slots in the array could be empty.
I've added some comments explaining this, please LMK if there's anywhere else you think should be augmented, or if you have some ideas to how we can improve on this.
} | ||
|
||
func (ads *acceptanceDataStore) stagingShard(stagingArea *model.StagingArea) *acceptanceDataStagingShard { | ||
return stagingArea.GetOrCreateShard(model.StagingShardIDAcceptanceData, func() model.StagingShard { |
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.
Please extract the create function to a separate method.
I'm pretty sure that currently, every time stagingShard
and similar functions are called, Go creates a new function along with a closure over the current scope. I imagine that to be quite costly.
Please do run benchmarks to make sure I'm not wrong though.
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.
BenchmarkStagingShardClosure-8 467047196 2.787 ns/op
BenchmarkStagingShardNoClosure-8 405023798 2.945 ns/op
They are virtually the same (actually NoClosure is a bit slower, I think I know why, but is miniscule difference anyway).
So seems like there's no point.
For reference, here's implemention of NoClosure:
func (ads *acceptanceDataStore) createStagingShard() model.StagingShard {
return &acceptanceDataStagingShard{
store: ads,
toAdd: make(map[externalapi.DomainHash]externalapi.AcceptanceData),
toDelete: make(map[externalapi.DomainHash]struct{}),
}
}
func (ads *acceptanceDataStore) stagingShardNoClosure(stagingArea *model.StagingArea) *acceptanceDataStagingShard {
return stagingArea.GetOrCreateShard(model.StagingShardIDAcceptanceData, ads.createStagingShard).(*acceptanceDataStagingShard)
}
}).(*acceptanceDataStagingShard) | ||
} | ||
|
||
func (adss acceptanceDataStagingShard) Commit(dbTx model.DBTransaction) 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.
Please go over all the shard types and make sure that the method receivers are pointers.
@@ -11,22 +11,18 @@ import ( | |||
) | |||
|
|||
var bucket = database.MakeBucket([]byte("blocks")) | |||
var countKey = database.MakeBucket(nil).Key([]byte("blocks-count")) | |||
var countKey = database.MakeBucket(nil).Key([]byte("blocks-countCached")) |
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.
Did you mean to do this?
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.
Nope :/
Good catch. This would have turned my change to db-breaking.
@@ -72,3 +56,21 @@ func (css *consensusStateStore) deserializeTips(tipsBytes []byte) ([]*externalap | |||
|
|||
return serialization.DBTipsToTips(dbTips) | |||
} | |||
|
|||
func (csss *consensusStateStagingShard) commitTips(dbTx model.DBTransaction) 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.
Please consider moving this to consensus_state_staging_shard.go.
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.
Hmmm... this and commitVirtualUTXODiff were deliberately left in their respective files, since consensus-state-store is split to file according to themes, not types.
Thus I felt it makes more sense to leave them here, if you disagree lmk, I don't mind moving it to consensus_state_staging_shard.go too much
} | ||
|
||
func (css *consensusStateStore) commitVirtualUTXODiff(dbTx model.DBTransaction) error { | ||
hadStartedImportingPruningPointUTXOSet, err := css.HadStartedImportingPruningPointUTXOSet(dbTx) | ||
func (csss *consensusStateStagingShard) commitVirtualUTXODiff(dbTx model.DBTransaction) 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.
Please consider moving this to consensus_state_staging_shard.go.
|
||
func (hstss headersSelectedTipStagingShard) Commit(dbTx model.DBTransaction) error { | ||
if hstss.newSelectedTip == nil { | ||
return nil |
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.
Now that not all stores are necessarily committed, please check whether this should return an error instead.
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 moment someone does a read from a store it's staging shard is created.
Therefore, a staging shard might exist (and then it's Commit function will be called) while nothing needs to be commited.
// Since Commit happens in a DatabaseTransaction, a StagingArea is atomic. | ||
type StagingArea struct { | ||
shards [StagingShardIDLen]StagingShard | ||
isCommited 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.
Typo: isCommited -> isCommitted
This PR enables to address #1516