Simplify the vuHandle implementation #1492
Labels
evaluation needed
proposal needs to be validated or tested before fully implementing it in k6
executors
lower prio
refactor
As I mentioned in #1479 (review), I don't like how complex the
vuHandle
implementation has gotten. True, its job is very tricky, so I am a bit skeptical about my gut feeling we can simplify it... It has to deal with a few gnarly synchronization issues:gracefulStop
/gracefulRampDown
handling, which can require a VU that is in the process of gracefully shutting down to resume again, without ever returning the VU to the pool, if we suddenly ramp up. And we don't know how long the last iteration it's executing is going to be, so it can end at basically any time in that process, or not at all... 😭externally-controlled
executor...I initially thought that this will finally be a job for
sync.Cond
, but because of thecontext
we require for JS execution and deactivation, it really doesn't seem to be of much use, though I might be missing something 😞 That said, it might not be totally out of place in some bigger refactoring, for example if we use thechanged
atomic more broadly. That is, if instead of just signalling that something has changed, we use a few different values to signal the current stateStopped
/Running
/GracefullyStopping
that the executor is supposed to be in... But that has issues of its own, namely something has to cancel the VU context...Something else to consider... For
variable-looping-vus
executor, we can know the precise time each VU is supposed to run, including thegracefulStop
value. It will become easier to calculate once we ziprawStepEvents
andgracefulLimitEvents
in a single plan, to address #1473. So, instead of having a resident goroutine for each VU we want to run (i.e. a stoppedvuHandle
), we can launch new goroutines every time we ramp up, and give 2 unique contexts to each of them, somewhat similar to what we do with the executor contexts,maxDurationCtx, regDurationCtx, cancel := getDurationContexts()
... That would still leave the problem of what to do with theexternally-controlled
executor though...And it also won't solve the issues with rapid ramp-down, ramp-up events. In these, we may have a situation where a VU is in the process of gracefully stopping, but it's still executing its last iteration. And if, before the
gracefulRampDown
time expires, we ramp up to that VU again, the VU never has to stop. So, in this case, what we do on the iteration length - for short iteration, we would have returned the VU to the buffer, but for iterations longer than the gap, it should be as if there was never any interruption in the VU running at all. This is the trickiest issue that I can't think of any other way besides a "vuHandle
" to solve... 😞So yeah, leaving this here for some future time, if we have any bright ideas... Or, we can close this a few months from now and just use my ramblings above as a documentation/justification of the current approach 😅
The text was updated successfully, but these errors were encountered: