Skip to content
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

Deprecate random and weak_rng, add SmallRng #296

Merged
merged 5 commits into from
Mar 13, 2018

Conversation

vks
Copy link
Collaborator

@vks vks commented Mar 12, 2018

See #289.

Copy link
Member

@dhardy dhardy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good other than the replacement for weak_rng which I'm not sure about — we could just make users copy that snippet (at least it explains how it works), but I don't want to make common tasks hard (to remember how to do).

//! means that often a simple call to `rand::random()` or `rng.gen()` will
//! suffice, but sometimes an annotation is required, e.g.
//! `rand::random::<f64>()`.
//! The key function is `Rng::gen()`. It is polymorphic and so can be used to
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably wants a bit more re-writing, but this doesn't have to be done now.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think we should advertise Rng::sample or Distribution::sample instead and possibly get rid of Rng::gen. But this is still under discussion in #293.

use rand::seq::*;

#[bench]
fn misc_shuffle_100(b: &mut Bencher) {
let mut rng = weak_rng();
let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really not very ergonomic; we've gone from 1 identifier to 4 with lots of extra syntax too. Any better ideas?

Error handling is pedantic because thread_rng will almost never fail, but we can't really be removed from from_rng.

We could allow something like thread_rng().new_rng::<SmallRng>() but it's not a lot better and adds a function to Rng which doesn't have many other uses.

We could just rename weak_rng to small_rng. Not sure.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure it's an issue outside of small examples. Usually you want to reuse thread_rng(). Maybe something like the following makes it more clear in the examples:

// Create a big, expensive to initialize and slower, but unpredictable RNG.
// This automatically done only once per thread.
let mut thread_rng = thread_rng();
// Create small, cheap to initialize and fast RNG with a random seed.
// This is very unlikely to fail.
let mut small_rng = SmallRng::from_rng(&mut thread_rng).unwrap();

This is even more verbose, but it teaches the correct pattern.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's also wrong: thread_rng() is only slow on the first call per thread. SmallRng::new() would be faster if thread_rng was never otherwise used — but chances are good that it would be used somewhere, I guess (at least once std's hash function randomisation uses this, not its own version).

Yes, copy-pasting this is fine, but often people don't look up the doc, they just vaguely remember how to do something and think, ah, SmallRng::new() should work.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's also wrong: thread_rng() is only slow on the first call per thread.

That's what I was trying to say with "This automatically done only once per thread.", but I guess it could be said more clearly.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any better ideas?

We could implement NewRng for SmallRng such that it uses thread_rng(). However, this requires getting rid of the impl for SeedableRng or specialization, which is not stable yet.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think using NewSeeded everywhere is fine. It is also how things used to be until a few months ago. But it would be nice to mention the thread_rng() method in the documentation just to point out a potential (small) performance advantage. How often will initializing the RNG be a bottleneck?

And I am still not sure thread_rng() is used all that much always. There is std::collections::HashMap that may also use it in the future, and maybe a crates dependency. If it is otherwise not used, spinning up thread_rng for one initialization of SmallRng is wasteful.

@dhardy
Copy link
Member

dhardy commented Mar 12, 2018

Oh, and I was less sure about removing random(), but searching GitHub mostly shows boring test code and some examples of how not to use random.

@pitdicker
Copy link
Contributor

Looks good to me!

Now initializing using `NewRng` is used to simplify the examples. The
documentation for `SmallRng` recommends using `thread_rng` when
initializing a lot of generators.
@vks
Copy link
Collaborator Author

vks commented Mar 13, 2018

But it would be nice to mention the thread_rng() method in the documentation just to point out a potential (small) performance advantage.

I changed the examples to use NewRng and suggested the thread_rng variant in the documentation of SmallRng.

@dhardy
Copy link
Member

dhardy commented Mar 13, 2018

Looks good to me! @pitdicker feel free to merge.

One small thing stands out, but it's definitely beyond the scope of this PR: thread_rng() either succeeds or panics, while new() and from_rng(rng) return a Result. Since errors are rare and new is supposed to be a convenience function (also easy to avoid if required), perhaps new should not return a Result and simply panic on failure?

@pitdicker pitdicker merged commit 2a8cb17 into rust-random:master Mar 13, 2018
@pitdicker
Copy link
Contributor

Since errors are rare and new is supposed to be a convenience function (also easy to avoid if required), perhaps new should not return a Result and simply panic on failure?

Seems like a good idea to me (after getting used to it...)!

@vks vks deleted the remove-random branch March 13, 2018 15:46
@dhardy dhardy mentioned this pull request Mar 14, 2018
3 tasks
pitdicker added a commit that referenced this pull request Apr 4, 2018
Deprecate `random` and `weak_rng`, add `SmallRng`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants