-
Notifications
You must be signed in to change notification settings - Fork 183
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
Remove TLS by using lazy_static #25
Conversation
d89d521
to
e4c7274
Compare
I haven't reviewed this code closely, but I think it's less resource efficient than my PR. Plus if reading from file has failed during initialization, Personally I would prefer to go with my PR (i.e. improve efficiency at the cost of a somewhat more complex code), but I leave this decision to @dhardy. |
494d0c4
to
49cdb6a
Compare
Initially, I thought this PR and #14 were identical efficacy-wise, as your PR uses an After looking a little closer, it seems that while they are equivalent in the uncontested case, in the constested case where a thread has to block they are different. Your PR calls
This is a very good point. Is this a feature we would want to support? If so, I can add it in. |
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.
Looks good to me, other than one point mentioned I didn't check further.
For me, maintainable/comprehensible code is more important than absolute performance, hence I prefer this over #14.
Note that you use more memory, e.g. for
IIUC
How do you plan to do it? Initially I also wanted to use
Well, I think this code will be really rarely touched, so maintainability will not be a big issue. And code is really straightforward for anyone who is familiar with priniciples of synchronization primitives (the only tricky part is atomics ordering). I believe for such foundational and low-level library zero-costness and efficiency are quite important. |
1531b48
to
b7e5df8
Compare
This change should be ready for final review/merging. @dhardy I've made a few changes/simplifications since your review. The details are in the (edited) PR description. But this gist is:
@newpavlov on the issue of efficiency, this approach uses ~16 more bytes of static memory than #14, but it is much more CPU efficient, as the busy-waiting problem is no longer a concern.
The main issue would be the initial one-byte read of
Ya I missed that initially. If we wanted to have re-executable sync::Once, we would either need to use the panicking/poisoning methods, or roll our own synchronization primitive. Neither really seems worth it, as if you fail initialization once, it will probably never succeed anyway. |
You are right, but it can be reasonably worked around by replacing |
If the overhead of using an external type to manage synchronisation is just a few bytes, then that sounds like a win to me. @newpavlov can we convince you that this is a sufficiently good approach? If so then this just needs a fresh review from @newpavlov or myself, then we can merge this (and make a new release, unless @josephlr plans on keeping up this barrage of PRs a little longer). |
I never argued that it's not, just that we can do better (efficiency wise). :) While my preference is unchanged, but as I've said earlier I will leave choice to you, thus I am not against merging this PR. I haven't done a full review and don't plan to do it in several days at least, so it will be probably faster for you to review and merge. |
Good. As I said before (roughly), in my opinion "ultimate efficiency" shouldn't be our goal, but rather a compromise between efficiency, maintainability and "obvious correctness" (i.e. minimising usage of Yeah, I also can't do a full review right now. |
Can you also fix #37 as part of this PR? |
Fixed, rebased, and description update to close the bug. |
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.
@newpavlov happy if we merge?
Closes #13 and Closes #37
This PR presents a potential alternative to #14
Instead of using an
AtomicUsize
state machine for each time we need some global state, this PR just uses alazy_static
value to hold the result of any one-time initialization. Then, on first use, the initialization will be run.Now the only times we have to deal with global state are exactly where we use
lazy_static
:RawFd
for file-based randomnessgetrandom()
or a read from/dev/urandom
This change then allows for the following simplifications:
use_file
module now contains all the logic for file-based randomness, including platforms that use this as their fallback method.use_file::getranodm_inner
directly. This required some cleanup tolib.rs
.linux_android.rs
andsolaris_illumos.rs
have been greatly simplified.Note 1:
wasm32_bindgen
still usesthread_local!
, as theJsValue
s are a per-thread resource, and thus must be initialized for each thread.Note 2: The
lazy_static
crate also supports aspin_no_std
features, so this approach will still work onno_std
platforms. For example, if we wanted to check for RDRAND support (see #27), we could again just uselazy_static
.