-
Notifications
You must be signed in to change notification settings - Fork 13k
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
loop { thread::yield_now(); } causes 100% CPU usage #46774
Comments
From the manpage of the corresponding syscall on Linux:
Perhaps that is the case. Anyways this behaviour is 100% determined by the OS. That documentation about channels looks misleading, which is a relevant docs issue. |
This is a docs issue, not a perf issue. |
@gsollazzo please don't use the A-rustdoc label for doc bugs (I've had to untag a few). That label is specifically for issues about the rustdoc tool, not about issues with the contents of the stdlib docs. |
@Manishearth Ok, thanks! Will do :) |
Depending on your goals (latency, power consumption, progress opportunities for other threads) poll+busy-wait loops may require a mix of pause(x86)/yield(arm) instructions, yielding to the scheduler and sleeps. possibly with backoffs for the pause and sleep intervals.
|
@steveklabnik Since this is behavior is platform dependent, do we actually want to document it? As @the8472 mentioned |
Maybe the documentation needs to be updated. E.g. it says channels use yield to give up the thread, but that's not really true (at least skimming the implementation) yield is only used for backoff in some cases while thread::park is used to actually deschedule the thread. Additionally it would be good to mention that it's only a hint to the scheduler. Or link to the underlying OS primitive as an implementation note so people can learn about OS-specific behavior. |
Yes, I think a clarification would be best, along the lines of what @the8472 is talking about. |
Should there be a function that works just like |
I don't think such a thing belongs in the standard library because naive polling often is an anti-pattern. It prevents CPUs from entering power-save states and offers poor latency and scalability properties. And in the cases where other alternatives are not available it one usually uses a more sophisticated approach involving loops over noops, pause instructions, yields and sleeps with backoffs. Something like that might belong in a library since it needs to be tuned depending on platform and what one is waiting on. |
There's an issue with thread::yield_now() that causes it to eat CPU cycles when used in a loop. Recommended to use sleep(1ms) instead rust-lang/rust#46774
This may be fixed by PR 86916. |
There's an issue with thread::yield_now() that causes it to eat CPU cycles when used in a loop. Recommended to use sleep(1ms) instead rust-lang/rust#46774
I may be wrong, but I thought
thread::yield_now()
should work likethread::sleep_ms(1)
(yes, I known there's preferred Duration struct). This may be caused by Linux kernel and not Rust's fault, but it leads to 100% CPU usage and PC heating up.I tried this code:
And ended up with 100% usage on 4-core CPU.
Meanwhile replacing
thread::yield_now
withthread::sleep_ms(1)
drops usage to 0%. Also, following code usingsync::mpsc
(that according to documentation ofyield_now()
usesyield_now()
) also (thankfully) uses 0% of CPU time:rustc --version --verbose
:uname -a
:Linux pawel-pc 4.12.14-1-MANJARO #1 SMP PREEMPT Wed Sep 20 10:51:00 UTC 2017 x86_64 GNU/Linux
sudo cpupower frequency-info
:I tried both
sudo cpupower frequency-set -g powersave
andsudo cpupower frequency-set -g performance
. I was running all te code withcargo run --release
.The text was updated successfully, but these errors were encountered: