Skip to content

Commit f7e5f3e

Browse files
authored
Improve threads performance when running under rr (#35527)
Partr does a user space busy loop when no events are found (until some timeout expires), in the expectation that another thread might push some. When running under rr, all execution is serialized, so there's no other thread running simultaneously, and rr will happily let the thread busy loop until its timeslice (50ms or so) is expired. The result is a dramatic performance decrease in the threads test that is entirely unnecessary (even during regular execution it's not clear that busy waiting makes much sense on low-core CPUs, since we're potentially starving another thread of the execution time it needs to actually schedule some work). For now, just detect that we're running under rr and stop doing any sort of busy waiting in that case.
1 parent ad87100 commit f7e5f3e

File tree

1 file changed

+35
-0
lines changed

1 file changed

+35
-0
lines changed

src/partr.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,10 +275,45 @@ JL_DLLEXPORT int jl_enqueue_task(jl_task_t *task)
275275
}
276276

277277

278+
static int running_under_rr(void)
279+
{
280+
#ifdef _OS_LINUX_
281+
#define RR_CALL_BASE 1000
282+
#define SYS_rrcall_check_presence (RR_CALL_BASE + 8)
283+
static int checked_running_under_rr = 0;
284+
static int is_running_under_rr = 0;
285+
if (!checked_running_under_rr) {
286+
int ret = syscall(SYS_rrcall_check_presence, 0, 0, 0, 0, 0, 0);
287+
if (ret == -1) {
288+
// Should always be ENOSYS, but who knows what people do for
289+
// unknown syscalls with their seccomp filters, so just say
290+
// that we don't have rr.
291+
is_running_under_rr = 0;
292+
}
293+
else {
294+
is_running_under_rr = 1;
295+
}
296+
checked_running_under_rr = 1;
297+
}
298+
return is_running_under_rr;
299+
#else
300+
return 0;
301+
#endif
302+
}
303+
304+
278305
// sleep_check_after_threshold() -- if sleep_threshold ns have passed, return 1
279306
static int sleep_check_after_threshold(uint64_t *start_cycles)
280307
{
281308
JULIA_DEBUG_SLEEPWAKE( return 1 ); // hammer on the sleep/wake logic much harder
309+
/**
310+
* This wait loop is a bit of a worst case for rr - it needs timer access,
311+
* which are slow and it busy loops in user space, which prevents the
312+
* scheduling logic from switching to other threads. Just don't bother
313+
* trying to wait here
314+
*/
315+
if (running_under_rr())
316+
return 1;
282317
if (!(*start_cycles)) {
283318
*start_cycles = jl_hrtime();
284319
return 0;

0 commit comments

Comments
 (0)