Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Does the existing blocking detection not catch these cases? |
|
Not exactly these ones - not Await.result. I was investigating the spikes of io-blocker threads in particular scenarios (like massive client reconnect in http4s/blaze websockets), The existing blocking detector correctly showed UUID blocks However, this detector is probabilistic, it samples a random sibling from the pool's worker array and checks its Thread.State. Anything that goes through The code above from http4s/blaze is called only once in websocket lifetime, because there are massive bursts, it's pronounced (not enough io-blocker threads and new got spawned), but the unsafeRunSync thunk itself is a tiny and never got caught by sampler. TLDR: My change catches BlockContext entrances deterministically, each call site once, at the cost of one static boolean check |
|
What's not entirely clear to me: why warn about these? The WSTP intentionally works with
I'm not sure this is correct: I think it doesn't report, e.g., |
Indeed it does not, its concerns are only eventual blocking contexts on the main WSTP performs excellently and close to theoretically possible limits, if there are no blocking contexts at all, just running the fibers. Spawning the io-blocker threads and keeping a few of them - is not free and does create some overhead, but may be sufficient for the cases when the latency SLO is not too tight, also in cases when there are enough CPU cores to run these. The impact becomes visible when the A particular problem for which this tracking was added - a http4s/blaze websocket/edge service implementation, on a cloud pod sharing cores with other processes, getting hit by up to few thousands of the (reconnecting) clients in the same second. Up to a hundred io-blocker threads were seen spawning, resulting in increased reconnection latency. The problem spot could be found by (agentic) static code analysis, but with |
|
Thanks for the explanation. What's still not clear to me: if the goal is avoiding spawning extra threads (which is indeed a good goal), then why recommend " Out of curiosity, what was the solution for the issue you've encountered with http4s? Just using Loom, or did you do something else eventually? |
This small enhancement proven to be useful for high-level optimisation of cats effect work stealing pool:
It reports all places where an io-compute thread enters blocking state triggering io-blocker threads to spawn. This can be some syncrhonized {} block, directly or via many layers of dependencies.
Generally deemed safe for production, as multiple blocking attempts of the same stack won't be reported more than once.
Await.result or blocking { } - e.g. http4s blaze:
and indeed here it is -
https://github.com/http4s/blaze/blob/2ae13a74d55209b6573d5228d1aa94f0361a75d0/blaze-server/src/main/scala/org/http4s/blaze/server/WebSocketSupport.scala#L103-L104