May 15, 2023·4 min read·engineeringvalkeyredisobservabilityperformance

Redis 7.2 RC2 measures work inside the event loop

Redis 7.2 RC2 adds event-loop timing metrics and improves collection allocation. The instrumentation separates command execution from other work performed during a loop cycle.

A command-duration metric does not explain all the work performed while a server processes events. Redis also flushes persistence buffers and performs housekeeping around command execution. The second Redis 7.2 release candidate adds timing information for those parts of the loop, giving latency investigation a more specific account of where execution time went.

The 7.2 release notes date RC2 to May 15. The versioned candidate notes list the event-loop metrics together with small SADD and HSET optimizations and a jemalloc upgrade. These metrics are the most useful organizing change because they make it possible to discuss internal work separately from the application's measured request latency.

I have used Redis since its early releases, and I prefer diagnostics that name a measured interval. A report that a command was fast is incomplete when another part of the loop consumed time before the client received its result. The new counters help distinguish those questions without pretending to measure the entire client journey.

A cycle has an explicit timing boundary

Pull request 11963 records the loop start time after the event loop wakes. Before the next sleep, it calculates elapsed time and adds a duration sample. The measurement therefore concerns the active interval between those hooks. It does not treat the event poll's sleeping time as command execution.

The new statistics expose cycle counts and accumulated duration, together with accumulated command duration. They also calculate instantaneous cycles per second and average cycle duration. The implementation uses monotonic microsecond timestamps to calculate these intervals.

The difference between a cumulative duration and an instantaneous average matters. A sum increases as the process performs more work. A recent average describes samples over the implementation's moving window. Neither should be presented as a percentile of application request latency, since the instrumentation does not record that distribution.

The command-duration accumulator only adds a sample at the outer execution level. That condition avoids treating nested execution as independent work to be added indiscriminately to the outer command interval. Reading the instrumentation point explains what the sum represents more precisely than interpreting its name alone.

AOF and housekeeping have their own measurements

The patch times the AOF flush in the before-sleep path separately. It also measures housekeeping work in serverCron and portions of beforeSleep, excluding the I/O and AOF work counted elsewhere. These categories make the loop's non-command work visible.

The extra detail is placed under INFO DEBUG. The patch's tests explicitly verify that the debug AOF duration field does not appear in either ordinary INFO output or INFO ALL. A collector that relies on the latter cannot assume it has retrieved every new diagnostic field.

The following commands illustrate the two relevant sections. They inspect the server and do not enable a different persistence policy.

INFO STATS
INFO DEBUG

The stats section includes eventloop_cycles, eventloop_duration_sum, and eventloop_duration_cmd_sum. The debug section includes AOF and housekeeping duration sums, the maximum observed cycle duration, and the maximum command count in a cycle. Those maxima describe observed loop behavior since the associated statistics were initialized or reset.

A maximum can establish that a long cycle occurred. It cannot identify which external request saw the largest delay or provide the frequency of long cycles. That would require a different measurement. The new fields are useful because their boundaries are narrower and inspectable, not because one maximum replaces all latency instrumentation.

Reset behavior affects interpretation

The patch resets duration statistics alongside other server statistics. Its tests call CONFIG RESETSTAT before observing the instantaneous values. A monitoring system that compares cumulative samples must therefore account for a reset rather than interpreting a lower total as negative work.

The instantaneous metric helper is also generalized. It computes a quotient from changes in a value and a base, so the same mechanism can represent rates over time or average duration per cycle. A cycle-duration average uses elapsed work as the numerator and completed cycles as the denominator.

That implementation detail prevents a common ambiguity. Cycles per second and microseconds per cycle are related but different quantities. A server can process more commands within one cycle without increasing its number of cycles by the same factor. The new maximum command-count field exposes another part of that relationship.

Collection allocation uses the request's size hint

Pull request 12019 changes collection creation using the number of arguments supplied to SADD and HSET. A sufficiently large incoming operation can select or convert to a hash-table representation and expand its dictionary before processing the values one by one.

For sets, the factory receives a size hint and uses it when choosing among integer-set, listpack, and hash-table representations. Existing compact sets can also convert based on the incoming hint. Hash insertion similarly estimates new fields from the incoming field-value pairs.

The source comments state the tradeoff. The hint assumes that many incoming values are unique. Duplicate-heavy input can therefore cause excess allocation relative to the final number of distinct members or fields. The optimization exchanges that possibility for avoiding repeated work during a large insertion.

This is a concrete performance change, but the release notes describe it as minor and supply no universal throughput figure. Its mechanism concerns representation selection and capacity planning within an operation. It does not make every SADD request faster by a fixed percentage.

The allocator change addresses a different failure

RC2 upgrades the bundled jemalloc to 5.3.0. The release notes say this resolves a rare fork-child hang. That is a reliability correction distinct from the collection preallocation changes, even though both concern memory-related implementation work.

I find the combination useful because it improves both diagnosis and specific execution paths. Event-loop timers explain measured work within defined boundaries. Collection hints reduce avoidable allocation work while retaining an explicit duplicate-input tradeoff. The allocator update addresses its separately reported hang, with the candidate still subject to the release notes' warning that RC versions are for early testing.