Reduces the frequency of LockSupport.unpark calls in ZScheduler, which is a hot-path JVM syscall identified as a bottleneck in #9878.
maybeUnparkWorker is called on every task submission and every time a worker transitions from searching → found work. Inside, it unconditionally calls idle.poll() (a ConcurrentLinkedQueue CAS) and, when successful, LockSupport.unpark — both expensive operations.
maybeUnparkWorker — three fast-path early returnsprivate def maybeUnparkWorker(currentState: Int): Unit = {
val currentSearching = currentState & 0xffff
if (currentSearching > 0) return // someone is already searching
val currentActive = (currentState & 0xffff0000) >> 16
if (currentActive == poolSize) return // all workers busy
if (idle.isEmpty) return // nothing to unpark
val worker = idle.poll()
if (worker ne null) {
state.getAndAdd(0x10001)
worker.active = true
LockSupport.unpark(worker)
}
}
currentSearching > 0: If at least one worker is already scanning for tasks, waking another is wasteful — the searching worker will find and then call maybeUnparkWorker itself if more are needed. This is the most impactful guard on a loaded system.idle.isEmpty: Avoids the CAS + node allocation of poll() when the queue is already empty.submit — conditional notification on local-queue successPreviously, every submit called maybeUnparkWorker unconditionally. Now:
currentActive < poolSize. When the submitting thread is itself a ZScheduler.Worker, it will process its local queue in the next iteration; waking an idle thread is only useful if there is spare capacity.currentSearching > 0 guard can delay waking idle threads under pathological scheduling. In practice, the searching worker resolves within microseconds and either finds work (cascade-notifying as needed) or parks again.idle.isEmpty is non-linearizable: ConcurrentLinkedQueue.isEmpty is O(1) but can return a stale false. The subsequent poll() null-check handles this safely.This is a performance-only change with no behavioral differences under correct execution. The existing test suite covers correctness.
Fixes #9878
/claim #9878
hhhcccbbb
@hhhcccbbb
ZIO
@ZIO