Lumiera  0.pre.03
»edit your freedom«
load-controller.hpp File Reference

Go to the source code of this file.

Description

Scheduler resource usage coordination.

Operating the render activities in the engine involves several low-level support systems, which must be actively guided to remain within sustainable limits. While all parts of the engine are tuned towards typical expected scenarios, a wide array of load patterns may be encountered, complicating any generic performance optimisation. Rather, the participating components are designed to withstand a short-term imbalance, expecting that general engine parametrisation will be adjusted based on moving averages.

Principles for Engine Load Control

Scheduling and dispatch of Activities are driven by active workers invoking the Scheduler-Service to retrieve the next piece of work. While this scheme ensures that the scarce resource (computation or IO capacity) is directed towards the most urgent next task, achieving a smooth operation of the engine without wasted capacity requires additionally to control the request cycles of the workers, possibly removing excess capacity. Whenever a worker pulls the next task, an assessment of the timing situation is conducted, and the worker is placed into some partition of the overall available capacity, to reflect the current load and demand. Workers are thus moved between the segments of capacity, preferring to assign work to workers already in the active segment, thereby allowing idle workers to be shut down after some time.

The key element to decide upon the classification of a worker is the current scheduling situation: are some Activities overdue? does the next Activity to be considered reach far into the future? If there is immediately imminent work, then capacity is kept around; otherwise the capacity can be considered to be in excess for now. A worker not required right now can be sent into a targeted sleep delay, in order to shift its capacity into a zone where it will more likely be required. It is essential to apply some randomisation on these capacity shifts, in order to achieve an even distribution of free capacity and avoid contention between workers asking for new assignments.

When a worker becomes available and is not needed at the moment, the first thing to check is the time of the next approaching Activity; this worker can then be directed close to this next task, which thereby has been tended for and can be marked accordingly. Any further worker appearing meanwhile can then be directed into the time zone after the next approaching task. Workers immediately returning from active work are always preferred for assigning new tasks, while workers returning from idle state are typically sent back into idle state, unless there is direct need for more capacity.

Load indicator

A fusion of some operational values is used to build a heuristic indicator of current scheduler load. These values can be retrieved with low overhead.

  • the fraction of maximal concurrency actually used
  • a sampling of the lag, i.e. the average distance to the next task; this observation is sampled whenever a worker asks for more work.
See also
scheduler.hpp
SchedulerLoadControl_test
SchedulerService_test::verify_LoadFactor()
SchedulerStress_test
Todo:
WIP-WIP 11/2023 »Playback Vertical Slice«

Definition in file load-controller.hpp.

#include "lib/error.hpp"
#include "lib/nocopy.hpp"
#include "lib/util.hpp"
#include "lib/format-cout.hpp"
#include <cmath>
#include <atomic>
#include <chrono>
#include <utility>
#include <functional>

Classes

class  LoadController
 Controller to coordinate resource usage related to the Scheduler. More...
 
struct  LoadController::Wiring
 

Functions

TimeValue _uTicks (std::chrono::microseconds us)
 

Variables

const double LAG_SAMPLE_DAMPING = 2
 smoothing factor for exponential moving average of lag;
 
Duration NEAR_HORIZON {_uTicks (50us)}
 what counts as "imminent" (e.g. for spin-waiting)
 
Duration SLEEP_HORIZON {_uTicks (20ms)}
 schedules beyond that horizon justify going idle
 
Duration STANDARD_LAG {_uTicks(200us)}
 Experience shows that on average scheduling happens with 200µs delay.
 
Duration WORK_HORIZON {_uTicks ( 5ms)}
 the scope of activity currently in the works
 

Namespaces

 vault
 Vault-Layer implementation namespace root.
 
 vault::gear
 Active working gear and plumbing.
 

Class Documentation

◆ vault::gear::LoadController::Wiring

struct vault::gear::LoadController::Wiring
Class Members
function< size_t()> maxCapacity
function< size_t()> currWorkForceSize
function< void(uint)> stepUpWorkForce
+ Collaboration diagram for LoadController::Wiring: