Skip to content

Waking a sleep triggers an expensive InterruptedException #9140

@headius

Description

@headius

RubyThread.sleep with a Lock currently uses a Condition to release and await that lock's signal:

public void sleep(Lock lock, long millis) throws InterruptedException {
assert Thread.currentThread() == getNativeThread();
executeTaskBlocking(getContext(), lock.newCondition(), Status.NATIVE, new Task<Condition, Object>() {
@Override
public Object run(ThreadContext context, Condition condition) throws InterruptedException {
if (millis == 0) {
condition.await();
} else {
condition.await(millis, TimeUnit.MILLISECONDS);
}
return null;
}
@Override
public void wakeup(RubyThread thread, Condition condition) {
thread.getNativeThread().interrupt();
}
});
}

In order to wake up the sleeping thread, this logic calls interrupt. This effectively terminates the sleep, but also raises an InterruptedException, which in turn requires a full stack trace and greatly adds to the overhead of a sleep wake-up.

This logic is used many places, such as for Mutex#sleep and ConditionVariable#await (which uses Mutex#sleep). The result is that the throughput of any sleep/wakeup or await/signal systems has much more overhead than it should. Waking a sleeping thread should require no more than signalling the sleep lock to unpark the sleeping thread and attempt to reacquire the lock.

This is a source of overhead in the Puma thread pool, resulting in excess allocation, GC, and VM synchronization overhead (to build the stack trace). See puma/puma#3788 for some discussion of this.

We need to fix this to do a simple condition-based signal to wake the sleeping thread.

This may also require some rework of how Mutex and ConditionVariable are implemented.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions