Re:On Java/JVM: Loom and Thread Fairness
by anonymousDan on Friday June 03, 2022 @04:03AM
(#31605514)
Seems like safepoints are an ideal way to do this. It sounds similar in ways to how the BEAM runtime for Elixir/Erlang will count reductions and preempts a lightweight process. I guess the interesting question is whether the same safepoint testing mechanism can be reused directly or whether some more complex logic is required on the critical path
Putting an if statement in your loops shall slow down your loops. Instead chunk/partition the loop and run it in chunks.
Re:On Java/JVM: Loom and Thread Fairness
by test-account on Thursday June 02, 2022 @07:30PM
(#31601958)
Agree. Let's document this trick and I'm happy with that unfair scheduling inconvenience for CPU heavy operations.
Seconded. Although I think Thread::yield should do what it says on the tin in the case of lightweight threads and it's hard to understand why they chose to not make it so, I don't care much. If the only problem I have to anticipate to get the full benefit of a well behaved lightweight threat scheduling is strategically sprinkling yield points inside those few tight loops that might actually threaten to hog a core then it's a net win.
Thinking about this further, a pragmatic enhancement to Thread::yield might look like this:
enum Hint {
ALWAYS,
FREQUENT,
SOMETIMES,
INFREQUENT,
NEVER
}
Thread::yield(Hint);
The method could be intrinsic to the compiler+runtime to provide runtime optimization (loop unrolling, tuning, etc.) of the 2nd - 4th cases. This would neatly avoid the need to: long n = 0;
while (true) {
// stuff
if (++n > SOME_LIMIT) {
n = 0;
// yield here
}
}
... or similar.
Re:On Java/JVM: Loom and Thread Fairness
by anonymousDan on Friday June 03, 2022 @04:04AM
(#31605528)
Having to do it manually is tedious and error prone IMHO. Better to have a reasonably good automated mechanism that you can disable if you wish).
> tedious and error prone IMHO
It's neither. The frequency of non-blocking CPU bound sections of most applications is low and so the need to introduce scheduling hints is also infrequent. Aside from an endless, non-blocking loop that never yields omitting possibly beneficial yield points isn't an error; scheduling will not be ideal but the process will ultimately produce the same result.
Some GCs need to reach a safepoint before doing their work; and when a classic Thread is chugging along in a tight loop, that thread is blocking the whole system for a pending GC.
One hacky fix is to provide an opportunity for a safepoint (System.out.print every 10k iterations). Other tools like JVM command line options allow for observing safepoint triggering.
The same goes for virtual threads: inserting a Thread.sleep(1L) every nth iteration of a tight loop does it.
Also there was talk specifying a custom scheduler for the virtual threads. That would not help in inserting switching opportunities, but it would give a way to define what kind of fairness you want.