-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
More improvements to std::rand #9695
Conversation
} | ||
#[cfg(unix)] | ||
#[fixed_stack_segment] #[inline(never)] | ||
fn new_sched_rng() -> XorShiftRng { |
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 native reading from /dev/urandom
. (Bringing this to particular attention since it's going outside of Rust's safety & is fairly core to the runtime.)
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 seems a bit of a shame that you can't use an explicit seed from an existing source that it's the OS, but I'm not sure that there's really a great way to avoid this.
Just from reading the PR description I like most of it. I'm not so sure about |
@kballard: the user has full control over all the memory in the process already, so I don't really see that as a problem |
(IRC discussion: https://botbot.me/mozilla/rust-internals/msg/6574768/) |
I agree with @kballard, but am not sure how it'd be implemented. |
cc #4958, the initial implementation of a re-seeding IsaacRng instance (I believe that this was lost when everything moved to rust). |
@@ -642,6 +636,62 @@ class raw_thread: public rust_thread { | |||
|
|||
#endif | |||
|
|||
#if defined(__WIN32__) | |||
void | |||
win32_require(LPCTSTR fn, BOOL ok) { |
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.
From looking at these functions, there doesn't seem to be a lot of reasons why they're implemented in C++ rather than rust.
Of these four:
win32_require
- this looks like just a fancy wrapper aroundFormatMessage
. I think that theFormatMessage
may actually already be implemented bystrerror
buries in thelibc
module, so this function can probably get removed.rust_win32_rand_acquire
- This looks like it may be the most difficult to put into rust. The constantsPROV_RSA_FULL
and the relatedCRYPT_*
ones would be a pain to have to re-define in rust. This function seems like it could stick around in C++ (with a comment explaining why it's not in rust).rust_win32_rand_gen
- This seems like it could easily be put into rust.rust_win32_rand_release
- This also seems like it could easily be put into rust.
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.
As I said on IRC, this appears to be slightly more difficult than it seems since (as far as I can tell from the MSDN docs), FormatMessage
& GetLastError
are different to errno
& strerror
. I don't have a windows computer to be able to test/iterate on this effectively, so I'm punting this to a later PR and/or filing a bug.
My name is Alex and I approve this message. (r=me with brson's comments addressed). |
This is 2x faster on 64-bit computers at generating anything larger than 32-bits. It has been verified against the canonical C implementation from the website of the creator of ISAAC64. Also, move `Rng.next` to `Rng.next_u32` and add `Rng.next_u64` to take full advantage of the wider word width; otherwise Isaac64 will always be squeezed down into a u32 wasting half the entropy and offering no advantage over the 32-bit variant.
…Readers respectively. The former reads from e.g. /dev/urandom, the latter just wraps any std::rt::io::Reader into an interface that implements Rng. This also adds Rng.fill_bytes for efficient implementations of the above (reading 8 bytes at a time is inefficient when you can read 1000), and removes the dependence on src/rt (i.e. rand_gen_seed) although this last one requires implementing hand-seeding of the XorShiftRng used in the scheduler on Linux/unixes, since OSRng relies on a scheduler existing to be able to read from /dev/urandom.
This is implemented as a wrapper around another RNG. It is designed to allow the actual implementation to be changed without changing the external API (e.g. it currently uses a 64-bit generator on 64- bit platforms, and a 32-bit one on 32-bit platforms; but one could imagine that the IsaacRng may be deprecated later, and having this ability to switch algorithms without having to update the points of use is convenient.) This is the recommended general use RNG.
…tes a certain number of bytes. It is an "RNG adaptor" and so any RNG can be wrapped to have this behaviour.
This provides 2 methods: .reseed() and ::from_seed that modify and create respecitively. Implement this trait for the RNGs in the stdlib for which this makes sense.
It now: - can be explicitly seeded from user code (`seed_task_rng`) or from the environment (`RUST_SEED`, a positive integer) - automatically reseeds itself from the OS *unless* it was seeded by either method above - has more documentation
This lets the C++ code in the rt handle the (slightly) tricky parts of random number generation: e.g. error detection/handling, and using the values of the `#define`d options to the various functions.
The f32 generator now just uses a single u32, and the f64 uses a single u64. This will make both significantly faster, especially on 64-bit platforms.
This much better handled by directly calling out to `OSRng` where appropriate.
This stops us relying on Default here.
A pile of changes to `std::rand`: - Add the 64-bit variant of the ISAAC Rng. This also splits the `Rng.next() -> u32` method into `Rng.next_u32() -> u32` and `Rng.next_u64() -> u64` to be able to actually take advantage of the wider numbers. They have default implementations in terms of each other. (This is ~2× faster than the 32 bit one for generating anything larger than a `u32` on 64-bit computers.) - Add `ReaderRng` which just wraps a reader as an RNG, useful for `/dev/urandom`, `/dev/random`, `/dev/hwrng`, etc. This also adds the overrideable `fill_bytes` method to `Rng`, since readers can "generate" randomness more than just 8 bytes at a time. - Add an interface to `/dev/urandom` (and the windows API) that implements `Rng` (`os::OSRng`) so that it is a first-class randomness source. This means that experimenting with things like seeding hashmaps from it will be much easier. It deletes most of the C++ supporting the old form, except for thin wrappers around the Windows API; I don't have access to a windows with Rust other than the try branch. ( **Note:** on unices, this means that `OSRng` requires the runtime, so it's not possible to use it to seed the scheduler RNG; I've replaced it with direct libc calls for reading from `/dev/urandom`.) - Add the "blessed" `StdRng` which means users who just want a random number generator don't need to worry about the implementation details (which will make changing the underlying implementation from Isaac to something else will be easier, if this every happen). This actually changes between the 32 and 64-bit variants of Isaac depending on the platform at the moment. - Add a `SeedableRng` trait for random number generators that can be explicitly seeded, - Add the `ReseedingRng` wrapper for reseeding a RNG after a certain amount of randomness is emitted. (The method for reseeding is controlled via the `Reseeder` trait from the same module) - changes to the task rng: - uses `StdRng` - it will reseed itself every 32KB, that is, after outputting 32KB of random data it will read new data from the OS (via `OSRng`) - Implements `Rand` for `char`, and makes the `f32` and `f64` instances more reasonable (and more similar to most other languages I've looked at). - Documentation, examples and tests
[`unused_async`]: don't lint if paths reference async fn without immediate call Fixes rust-lang#9695 Fixes rust-lang#9359 Clippy shouldn't lint unused `async` if there are paths referencing them if that path isn't the receiver of a function call, because that means that the function might be passed to some other function: ```rs async fn f() {} // No await statements, so unused at this point fn requires_fn_future<F: Future<Output = ()>>(_: fn() -> F) {} requires_fn_future(f); // `f`'s asyncness is actually not unused. ``` (This isn't limited to just passing the function as a parameter to another function, it could also first be stored in a variable and later passed to another function as an argument) This requires delaying the linting until post-crate and collecting path references to local async functions along the way. changelog: [`unused_async`]: don't lint if paths reference async fn that require asyncness
A pile of changes to
std::rand
:Rng.next() -> u32
method intoRng.next_u32() -> u32
andRng.next_u64() -> u64
to be able to actually take advantage of the wider numbers. They have default implementations in terms of each other. (This is ~2× faster than the 32 bit one for generating anything larger than au32
on 64-bit computers.)ReaderRng
which just wraps a reader as an RNG, useful for/dev/urandom
,/dev/random
,/dev/hwrng
, etc. This also adds the overrideablefill_bytes
method toRng
, since readers can "generate" randomness more than just 8 bytes at a time./dev/urandom
(and the windows API) that implementsRng
(os::OSRng
) so that it is a first-class randomness source. This means that experimenting with things like seeding hashmaps from it will be much easier. It deletes most of the C++ supporting the old form, except for thin wrappers around the Windows API; I don't have access to a windows with Rust other than the try branch. ( Note: on unices, this means thatOSRng
requires the runtime, so it's not possible to use it to seed the scheduler RNG; I've replaced it with direct libc calls for reading from/dev/urandom
.)StdRng
which means users who just want a random number generator don't need to worry about the implementation details (which will make changing the underlying implementation from Isaac to something else will be easier, if this every happen). This actually changes between the 32 and 64-bit variants of Isaac depending on the platform at the moment.SeedableRng
trait for random number generators that can be explicitly seeded,ReseedingRng
wrapper for reseeding a RNG after a certain amount of randomness is emitted. (The method for reseeding is controlled via theReseeder
trait from the same module)StdRng
OSRng
)Rand
forchar
, and makes thef32
andf64
instances more reasonable (and more similar to most other languages I've looked at).