Skip to content

Agrona Agents

Agrona is another open source project by the authors of Aeron. It is a treasure trove of "High Performance data structures and utility methods for Java". It is widely used by Aeron and includes:

  • Many allocation-free collections, such as maps and sets that can contain primitive keys / values (no boxing), and have allocation-free iterators
  • Clocks - various clock interfaces and implementations, which allow controlling time in tests
  • Queues - lock-free queue implementations
  • RingBuffer - one-to-one and many-to-one ring buffers for passing messages between threads
  • Buffers - various atomic buffers for on and off-heap memory
  • Counters - off-heap counters for sharing numeric values between applications (used throughout Aeron)
  • Agents - a small framework for writing Agents

Agents

An Agent defines a unit of work that fulfills a role within a system. When invoked to 'do work', an Agent should perform one cycle of its work, known as a duty cycle, then return some indication of how much work it did. It will be invoked repeatedly, on the same thread. Each duty cycle should be short, so big chunks of work should be broken up into smaller pieces, any I/O should be non-blocking, etc. Agents often contain a state machine, so they can track where they are up to across different duty cycles.

As an example, Aeron Transport has a Sender Agent, whose role is to send messages to a receiver's machine. In its duty cycle, it scans log buffers for new messages and if it finds any, it sends at most one UDP packet for each log buffer. It then returns the number of bytes sent. If it didn't send anything, it returns zero, i.e. it did no work.

void idle(int workCount) IdleStrategy int doWork() Agent AgentRunner IdleStrategy Agent Agent Agent CompositeAgent AgentRunner

The Agent model has a good separation of concerns. An Agent defines some work to be performed, but not the threading model. This gives flexibility in how threads are allocated to Agents. An AgentRunner provides a Thread. It could be dedicated to servicing one Agent, for higher performance, or in a more constrained environment, it could service several Agents via a CompositeAgent.

An AgentRunner invokes its Agent, then feeds the amount of work done into an IdleStrategy - it repeats this over and over. The IdleStrategy decides how to idle. If the Agent did some work, the IdleStrategy would normally return immediately, so the Agent can perform another duty cycle. If the Agent is currently quiet and did no work, the IdleStrategy would idle in some way.

Several IdleStrategies are available, to idle in different ways, e.g.:

  • the NoOpIdleStrategy does not idle, which can be used in low latency production environments at the cost of high CPU load
  • the BackoffIdleStrategy backs off more and more, while the Agent continues to be idle - this is often used during development
  • the YieldingIdleStrategy calls Thread.yield() when the Agent is idle

An alternative to AgentRunner is AgentInvoker. It doesn't allocate a thread and provides a small wrapper around the Agent, so you can invoke the Agent on your own thread. It doesn't have an IdleStrategy. This is for really constrained environments, where you have a thread doing some other work, and also want it to service one or more Agents.

All the big components with Aeron Transport, Archive and Cluster are Agents. This gives a lot of flexibility in how threads are used in an Aeron based system.

DutyCycleStallTracker

DutyCycleStallTracker is provided by Aeron, not Agrona, but worth mentioning here. It can be used within an Agent to detect when the duration since the last doWork() invocation is longer than a given threshold, i.e. whether the Agent is being starved of cycle times. It updates two Counters that are passed into it, along with the threshold. One Counter is for the maximum cycle time, the other is for the number of threshold breaches.

It is used in all the Agrona Agents within Aeron:

  • Aeron Transport: Driver Conductor, Sender and Receiver
  • Aeron Archive: Archive Conductor, Recorder and Replayer
  • Aeron Cluster: Consensus Module and Clustered Service