-
Notifications
You must be signed in to change notification settings - Fork 211
Remove TLS by using lazy_static #25
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
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
.