-
Notifications
You must be signed in to change notification settings - Fork 2
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
Changes in ArbitraryGenerator #502
Draft
purusang
wants to merge
1
commit into
main
Choose a base branch
from
STR-551-fix-arbitrary-gen-slow
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,46 +1,40 @@ | ||
use std::sync::atomic::{AtomicUsize, Ordering}; | ||
|
||
use arbitrary::{Arbitrary, Unstructured}; | ||
use rand::{rngs::OsRng, RngCore}; | ||
use rand::{thread_rng, RngCore}; | ||
|
||
pub mod bitcoin; | ||
pub mod bridge; | ||
pub mod evm_ee; | ||
pub mod l2; | ||
|
||
const ARB_GEN_LEN: usize = 1 << 24; // 16 MiB | ||
// Smaller buffer size as compared to 2^24 | ||
const ARB_GEN_LEN: usize = 128; | ||
|
||
pub struct ArbitraryGenerator { | ||
buf: Vec<u8>, | ||
off: AtomicUsize, | ||
rng: rand::rngs::ThreadRng, // Thread-local RNG | ||
buf: Vec<u8>, // Persistent buffer | ||
} | ||
|
||
impl Default for ArbitraryGenerator { | ||
fn default() -> Self { | ||
Self::new() | ||
} | ||
} | ||
|
||
impl ArbitraryGenerator { | ||
pub fn new() -> Self { | ||
Self::new_with_size(ARB_GEN_LEN) | ||
ArbitraryGenerator { | ||
rng: thread_rng(), | ||
buf: vec![0u8; ARB_GEN_LEN], | ||
} | ||
} | ||
|
||
pub fn new_with_size(n: usize) -> Self { | ||
let mut buf = vec![0; n]; | ||
OsRng.fill_bytes(&mut buf); // 128 wasn't enough | ||
let off = AtomicUsize::new(0); | ||
ArbitraryGenerator { buf, off } | ||
pub fn new_with_size(s: usize) -> Self { | ||
ArbitraryGenerator { | ||
rng: thread_rng(), | ||
buf: vec![0u8; s], | ||
} | ||
} | ||
|
||
pub fn generate<'a, T: Arbitrary<'a> + Clone>(&'a self) -> T { | ||
// Doing hacky atomics to make this actually be reusable, this is pretty bad. | ||
let off = self.off.load(Ordering::Relaxed); | ||
let mut u = Unstructured::new(&self.buf[off..]); | ||
let prev_off = u.len(); | ||
let inst = T::arbitrary(&mut u).expect("failed to generate arbitrary instance"); | ||
let additional_off = prev_off - u.len(); | ||
self.off.store(off + additional_off, Ordering::Relaxed); | ||
inst | ||
pub fn generate<'a, T: Arbitrary<'a> + Clone>(&'a mut self) -> T { | ||
self.rng.fill_bytes(&mut self.buf); | ||
let mut u = Unstructured::new(&self.buf); | ||
T::arbitrary(&mut u).expect("Failed to generate arbitrary instance") | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 way this is written kinda makes having the random buf be a field pointless. Since we sample new randomness on each call it might as well just be a local and then we can just have this take
&self
. Also what happens if we consume more than the length of randomness in a call togenerate
? I'm not sure the best design approach here since it'd be nice to be able to make it deterministic if desired.Also should verify if it makes sense to include the rng as a field as opposed to just calling
thread_rng()
on every invocation. I'm not sure if there's a practical difference in terms of speed/determinism there.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 think the buf field is required because of lifetime issues. The random buf is generated inside the method which can't leave the method scope.
I don't really like having
mut
everywhere though. Maybe aRefCell
can be used for buffer(and for rng?), which should be fine since we probably won't be using a generator instance across multiple threads. What are your thoughts on 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.
The reason for having buf field is due to lifetime requirement, like @bewakes said.
We needed
&mut
due to having to update randomness on every call.It's a good concern, but I think having new_with_size() serves that purpose.
Both approaches definitely work, and don't see either way to be an issue.
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.
That's what I observed too.
Yeah, initially I did not like the idea of having to change multiple files to pass mutable arbitrary generator but due to lifetime requirement using RefCell was not helpful there.
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.
Oh christ I'm realizing how this api kinda sucks. I didn't see that
Arbitrary
has a lifetime param.Taking
&mut self
means I think you can have multiple invocations now can you? Since you'd overwrite the buffer that we have a hypothetical ref to in the value returned in the previous invocation.Is this an issue that we can deal with by generating the randomness upfront?
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.
Multiple
arb.generate()
? Yes.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 can't. Since you'd need to take an exclusive borrow while there was a shared borrow active.