Class ProgressTracker

java.lang.Object
org.opendaylight.raft.spi.ProgressTracker
Direct Known Subclasses:
AveragingProgressTracker

public abstract class ProgressTracker extends Object
Base class for tracking throughput and computing delays when processing stream of tasks.

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 Type
    Method
    Description
    final 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
    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
    One task is roughly estimated to take this long to close.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • 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 present
      enqueuedTicks - see TransitQueue#recordCompletion
      transmitTicks - see TransitQueue#recordCompletion
      execNanos - 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