-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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
math/rand: Read should return consistent results, regardless of buffer size #16124
Comments
Seems like something that's easily fixed. The one concern I see is compatibility. If someone relies on this broken behavior, their program may cease to function correctly. However, I don't think we have made any promises about the stability of math/rand as a pseudo-random source. And this is certainly a bug. So the compatibility concern is probably not relevant. |
I don't see the point behind this proposal. If you're giving math/rand a seed (and the same seed multiple times in different runs), it is because you're trying to make some nondeterministic code deterministic. But surely you're also issuing the same sized reads in that case?
In other words, why would you not fix the buffer size if you were trying to make a computation deterministic? |
CL https://golang.org/cl/24251 mentions this issue. |
Issue #8013 has some discussion about whether we could change the output of the That said, if we do change it, should we consider this change for |
I'm with @randall77; it's not clear to me why this needs to be the case. Is there a concrete context where you need this? |
@randall77 I would like to have deterministic sequence with known distribution but in the same time luxury of dealing with Say This is the natural way of thinking for me:
@josharian The reasonable expectation I believe is that, for instance, So that one could send that stream over the network, store on disk, etc. Then afterwards read it back (i.e. get It is convenient because one can use arbitrary-sized streams that could exceed RAM size, have many of them and just keep seed and length in order to be able to validate content. It is sound way to do some kinds of testing of network device, storage service, etc. And doing such testing one can't always fix buffer size because it could be determined by say network buffers (or say RPC mechanism and validator implementation could have different buffers). One of the real-world examples is TFTP library unit-tests, see https://github.com/pin/tftp/blob/master/tftp_test.go#L126 for instance. There is roll-your-own In general, I would expect that provided the same seed and calling no other methods on |
I agree with @dsnet that this might be worth getting in for 1.7. |
I see. It does sound useful to do One way to get the determinism you want would be to wrap |
I am a bit concerned about the backwards compatibility still. We've declined to do reasonable things with rand in the past. I wonder whether it would be preferable to do this in 1.8 and fix those other bugs as well, all in one release. If this were introduced in 1.7 the case for changing it now would be clear. |
Another case where we decided not to change math/rand because of compatibility issues: |
@josharian, @randall77, I remember reading through #13215 some time ago because of the concern related to backwards compatibility and trying to figure out the extent it can be changed now. My assumption is that the fix of existing
Other more radical changes I was thinking about are:
|
CL https://golang.org/cl/24520 mentions this issue. |
Updates #16124 Change-Id: Ib58f2bb37fd1559efc512a2e3cba976f09b939a0 Reviewed-on: https://go-review.googlesource.com/24520 Reviewed-by: Andrew Gerrand <[email protected]>
Read
returns byte sequence that depends on the buffer length. That's becauseRand
usesInt63
value to produce 7 random bytes and throws away unused bits fromInt63
when done with the particular call. Next call always starts with freshInt63
leaving "gap" from previousRead
if it was not finished on 7-bytes boundary.Therefore, you can't fix seed and read pseudo-random bytes deterministically without fixing buffer size.
Proposed fix
My proposal is to keep unused
Int63
reminder in theRand
struct. It let us fix the issue and still have the same bytes from the firstRead
call as we have now. The performance hit is minimal also. The downside is an extra state inRand
struct.One of the other options is to use only single byte from each
Int63
call. No state inRand
but the 2x-4x performance hit.go version
)?go version devel +f3d5478 Fri Jun 17 19:15:29 2016 +0000 linux/amd64
go env
)?This is play-adopted unit-test using
testing/iotest
that fails: https://play.golang.org/p/dbz-VlFPCaThe same random bytes stream no matter read buffer size used.
The text was updated successfully, but these errors were encountered: