joewitt commented on PR #11164:
URL: https://github.com/apache/nifi/pull/11164#issuecomment-5639826769

   Mark —
   
   On the 25 millisecond permit wait: I want to make sure we are comparing this 
to what timer-driven scheduling does today, not to a busy loop.
   
   Today. Each concurrent task is a delayed future on the existing FlowEngine 
pool. If the Processor is not due yet, it sits in the delayed queue. If it is 
due and all of the max timer-driven threads are already in onTrigger, it sits 
in the executor queue. There is no thread dedicated to that waiting task. Stop 
of a task that is not currently in onTrigger is cancel(false), which typically 
takes it off the queue immediately. Nothing wakes periodically just to ask “do 
I have a slot yet?”
   
   This change. Each concurrent task is a long-lived virtual thread for the 
whole time the component is RUNNING. When it cannot get a permit from the 
global semaphore, that thread parks in tryAcquire(25 milliseconds), wakes, 
checks whether it is still scheduled, and parks again. That loop does not exist 
on main.
   
   That is why the 25 millisecond interval is there: unschedule still does not 
interrupt an in-flight onTrigger, same as today’s cancel(false). A thread 
blocked in a plain acquire() would not notice Stop until a permit showed up. 
Polling is the compromise so a waiter can leave when the component is stopped.
   
   Where it is not worse. While a Processor is in onTrigger, Stop still waits 
for the invocation to return. Between invocations, you wait on the generation 
latch; unschedule can wake that wait immediately, which is at least as good as 
canceling a delayed future.
   
   Where it is a bit worse. The cost shows up only when work is queued behind 
the max-thread cap: scheduled concurrent tasks that do not currently hold a 
permit. Each of those virtual threads wakes about 40 times per second. That is 
new framework overhead. Stop of a waiter can also take up to 25 milliseconds, 
versus today’s cancel of a queued future, which is usually immediate.
   
   On a small graph, or when almost everyone already has a permit, this will 
not matter. On a large canvas with a small max thread count and many one-thread 
Processors, we pay a wait-for-capacity tax that the current pool does not pay. 
I do not think that is a merge blocker, but it is a real before-and-after 
difference.
   
   A cleaner shape, if you want Stop and permit handoff to stay as immediate as 
today: a condition that both unschedule and release signal, so waiters are not 
on a 25 millisecond timer.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to