Skip to content

Duty Cycles

If you've ever played a computer game, you've most likely interacted with a duty cycle (also referred to as an event loop). A duty cycle is the primary loop a system component undertakes. In the loop some tasks are performed and then it may optionally wait for some period of time. For a simple computer game, the duty cycle might be:

1
2
3
4
5
6
7
8
9
EpochClock clock = new SystemEpochClock();
while (true)
{
    long time = clock.time();
    processInput();
    update();
    render();
    Thread.sleep(MS_PER_FRAME - (clock.time() - time));
}

The sleep allows the game developer to control two things: the power consumption of the game and the number of frames per second. This is important as different CPUs have different performance characteristics, and game developers want their users to have a consistent experience across different hardware.

In typical Aeron applications we also make use of duty cycles. They run inside Agrona Agents, with the sleep of the above sample managed by the Idle Strategy. The duty cycle directly impacts the service's capability in terms of messages processed per second as well CPU consumption of the process.

Two typical duty cycles are below.

Business logic duty cycle

This is a typical duty cycle driven by some input message. To achieve a high throughput, the sleep (that is, idle strategy) applied would spend very little to no time delaying the duty cycle.

1
2
3
4
5
while (true)
{
    Command command = adaptInputBuffer();
    routeToAppropriateBusinessLogic(command);
}

The call to routeToAppropriateBusinessLogic() then would typically do something like calling a method on a stateful object such as a Replicated State Machine:

1
2
3
4
5
public void doSomething(command)
{
    processInput();
    emitEvents();
}

Connectivity duty cycle

This duty cycle is not driven by messages, but rather by a desire to manage connectivity to something. There is little point in this being called thousands of times a second, so the sleep applied in the duty cycle could be in the hundreds of milliseconds.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
EpochClock clock = new SystemEpochClock();
long openConnectionTime = [some value];
long closeConnectionTime = [some value];

while (true)
{
    long now = clock.time();
    if (!connected) 
    {
        if (now >= openConnectionTime && now < closeConnectionTime) 
        {
            connect();
        }
    }
    else
    {
        if (now < openConnectionTime || now >= closeConnectionTime) 
        {
            disconnect();
        }
    }
}