Class ProgressTracker
- Direct Known Subclasses:
AveragingProgressTracker
The idea is to improve throughput in a typical request-response scenario. Multiple "user" threads are submitting requests to a "frontend". The frontend does some pre-processing and then sends requests to (usually one) "backend". The backend does the main work and replies to the frontend, which reports to the the corresponding user. In terms of task processing, user threads are "opening" tasks and frontend is "closing" them. Latency of the backend may fluctuate wildly. To avoid backend running out of open tasks, frontend should maintain a queue of requests for users to submit tasks to. In order to avoid excessive memory consumption, there should be a back-pressure mechanism which blocks the user (submit) threads for appropriate durations. Users can tolerate moderately delayed responses, but they only tolerate small block (submit) times.
An ideal back-pressure algorithm would keep the queue reasonably full, while fairly delaying the user threads. In other words, backend idle time should be low, as well as user block time dispersion (as opposed to block time average, which is dictated by overall performance).
In order for an algorithm to compute reasonable wait times, various inputs can be useful, mostly related to timing of various stages of task processing. Methods of this class assume "enqueue and wait" usage, submit thread is supposed to block itself when asked to. The delay computation is pessimistic, it expects each participating thread to enqueue another task as soon as its delay time allows.
This class is to be used by single frontend. This class is not thread safe,
the frontend is responsible for guarding against conflicting access.
Time is measured in ticks (nanoseconds), methods never look at current time,
relying on now
argument where appropriate.
This means the sequence of now
argument values is expected to be non-decreasing.
Input data used for tracking is tightly coupled with TransitQueue#recordCompletion arguments.
- Author:
- Vratko Polak
-
Method Summary
Modifier and TypeMethodDescriptionfinal void
cancelDebt
(long now) Set nearestAllowed value to now.final void
closeTask
(long now, long enqueuedTicks, long transmitTicks, long execNanos) Track a task is being closed.protected final long
Get the value of default ticks per task this instance was created to use.protected abstract long
estimateIsolatedDelay
(long now) Give an estimate of a fair delay, assuming delays caused by other opened tasks are ignored.final long
openTask
(long now) Track a task that is being opened.final long
ticksStalling
(long now) Number of ticks elapsed (before now) since the last closed task while there was at least one open task.protected final double
ticksWorkedPerClosedTask
(long now) One task is roughly estimated to take this long to close.
-
Method Details
-
ticksStalling
public final long ticksStalling(long now) Number of ticks elapsed (before now) since the last closed task while there was at least one open task.- Parameters:
now
- tick number corresponding to caller's present- Returns:
- number of ticks backend is neither idle nor responding
-
defaultTicksPerTask
protected final long defaultTicksPerTask()Get the value of default ticks per task this instance was created to use.- Returns:
- default ticks per task value
-
ticksWorkedPerClosedTask
protected final double ticksWorkedPerClosedTask(long now) One task is roughly estimated to take this long to close.- Parameters:
now
- tick number corresponding to caller's present- Returns:
- total ticks worked divided by closed tasks, or the default value if no closed tasks
-
closeTask
public final void closeTask(long now, long enqueuedTicks, long transmitTicks, long execNanos) Track a task is being closed.- Parameters:
now
- tick number corresponding to caller's presentenqueuedTicks
- see TransitQueue#recordCompletiontransmitTicks
- see TransitQueue#recordCompletionexecNanos
- see TransitQueue#recordCompletion
-
openTask
public final long openTask(long now) Track a task that is being opened.- Parameters:
now
- tick number corresponding to caller's present- Returns:
- number of ticks (nanos) the caller thread should wait before opening another task
-
cancelDebt
public final void cancelDebt(long now) Set nearestAllowed value to now.This is useful when new a backend has just connected, after a period of no working backend present. The accumulated delays should not limit future tasks. The queue fullness and the averaged backend performance are kept, as they should result in good enough estimations for new tasks.
- Parameters:
now
- tick number corresponding to caller's present
-
estimateIsolatedDelay
protected abstract long estimateIsolatedDelay(long now) Give an estimate of a fair delay, assuming delays caused by other opened tasks are ignored.- Parameters:
now
- tick number corresponding to caller's present- Returns:
- delay (in ticks) after which another openTask() would be fair to be called by the same thread again
-