-
Notifications
You must be signed in to change notification settings - Fork 161
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
Bitfield improvements #506
Conversation
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.
I like the changes sooo much.
Only actual issue I have is that there will be inconsistencies in cases with the go implementation (specifically with the actors). The issue is that the bitfield is iterated and checked to be valid on instantiation which has an upfront cost but also in the cases of an invalid bitfield (or partially invalid) the go implementation will not error on serialization (which is an ErrSerialization
exit code) and instead will error when the invalid part of the bitfield is iterated over (ErrIllegalState
usually and in different places so it's possible another error was hit before).
One case that will for sure cause us to fork the network is if a bitfield is sent in params of a transaction that is invalid. We will fail immediately on deserialization and return that exit code, where the go implementation will either throw a different exit code or not error at all, which will fork the network.
To be clear though, I much prefer this way, it makes more sense for sure, but we need to match the go implementation and they are only erroring when the invalid ranges are iterated over.
Ok(()) | ||
}); | ||
Ok(st.info.sector_size) | ||
if declared_recoveries.is_empty() { |
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.
here as another potential inconsistency (would have failed on serialization instead of ErrIllegalState exit code)
vm/actor/src/builtin/miner/mod.rs
Outdated
format!("failed to union faults: {}", e), | ||
) | ||
})?; | ||
let all_declared = BitField::multi_union(&declared_sectors); |
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.
same here (sorry for comment spam)
let recoveries = &st.recoveries & &all_declared; | ||
let new_faults = &all_declared - &recoveries; |
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.
These two also (I'll stop checking for these now)
* initial market actor updates * fix market actor errs * fix linting issue * made requested changes * update error msg * added verifreg to internal send and mockrt * updated multimap error handling
* Bump dep versions * Refactor to new proofs types * Switch to from trait and cleanup
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, aside from Austins concerns
For future reference, Austin's concerns have been resolved — this is now consistent with the Go implementation |
@austinabell @ec2 I pushed some minor changes to deal with integer overflow in the same way the Go implementation does for which I had to drop down from ranges to runs because a trailing 0 run still shouldn't overflow 64 bits, which is why I'll make a separate PR for removing the |
Summary of changes
BitField
now always contains an encoded bitvec and never a decoded one, which means that most methods no longer need a&mut self
referenceRLEPlus
is an RLE+ encodedBitVec
that has been verified to be encoded correctlyBitField
andRLEPlus
work withusize
rather thanu64
in order to minimize numeric conversionsAHashMap
replacesFnvHashMap
due to speedups of around 30%-50% according to pretty rudimentary benchmarksRangeIterator
trait was added for working with lazy sequences of disjoint rangesRangeIterator
is still a regularIterator<Item = Range<usize>>
so you can still use them infor
loops and stuff like thatBitField
borrows some behavior fromHashMap
:union
,intersection
, anddifference
return (lazy)RangeIterator
s, and the|
,&
, and-
operators are their eager counterparts that returnBitField
sunion
for taking the union of any number ofBitField
s has been renamedmulti_union
BitField
can be iterated withranges()
as well as withiter()
which returns an iterator over the set bits of the bit fieldretrieve_set_indices
was therefore renamedbounded_iter(max: usize)
and was made public, it now also returns an iterator instead of aB: FromIterator
BitField::for_each
which can be directly replaced with.iter().try_for_each(...)
BitReader
andBitWriter
are used to efficiently read and write multiple bits at a time (up to 8) which significantly speeds up RLE+ encoding and decodingI think I haven't forgotten anything!
Reference issue to close
Closes #468