What latency metric should capture Redux middleware overhead before optimization?
0 reputation · 16 May 2022, 13:07 UTC
0 reputation · 16 May 2022, 13:07 UTC
Goal: Determine a reliable, low‑overhead metric that reflects the extra time introduced by Redux middleware on each state update so teams can decide whether optimization is warranted.
Constraints: Redux core does not prescribe a standard measurement; teams must choose between action‑processing latency, store mutation cost, or re‑render frequency. Profiling tools add overhead, and measurements taken in development may not match production characteristics, especially when middleware performs asynchronous work.
Questions: Which of these candidates best isolates middleware cost from reducer work? How can the measurement be kept lightweight enough for continuous monitoring? What threshold or trend should trigger a deeper optimization effort?
35275 reputation · 16 May 2022, 23:41 UTC
Use action-to-reducer latency. It is the elapsed time from when an action is dispatched to the moment it enters the root reducer. This isolates the synchronous middleware chain cost from reducer execution and downstream UI rendering.
Capture high-resolution timestamps at the start of the chain and immediately before the reducer call.
const timingMiddleware = store => next => action => {
const start = performance.now();
const result = next(action);
const end = performance.now();
if (Math.random() < 0.02) {
// sample 2% to limit observer effect
}
return result;
};
Place this middleware first. The delta end - start is action-to-reducer latency.
Separate reducer cost with a wrapper:
const reducerTiming = reducer => (state, action) => {
const start = performance.now();
const nextState = reducer(state, action);
const end = performance.now();
return nextState;
};
Middleware overhead = action-to-reducer latency - reducer latency.
For thunks, sagas or observables, synchronous chain timing only captures dispatch overhead. Async side-effect duration is a separate dispatch-to-completion metric and should not be mixed with synchronous middleware cost.
| Metric | Investigate if |
|---|---|
| Action-to-reducer p95 | > 2 ms desktop, > 5 ms low-end mobile |
| Middleware overhead trend | Sustained 20% increase over 3+ releases |
| Single middleware delta | > 1 ms vs baseline with middleware toggled off |
Measure without Redux DevTools and redux-logger enabled, as they add 0.5-3 ms per action in development.
Use comments to ask for clarification. Post a solution as an answer.
35,275 reputation · 16 May 2022, 14:34 UTC
Instead of manually inserting performance.now() calls, you can wrap the middleware chain with the standard performance.mark and performance.measure APIs. Place a mark at the start of the first middleware, another mark just before the reducer is invoked, then create a measure named “redux-middleware-overhead”. The browser stores these entries with minimal overhead, and they can be read later via performance.getEntriesByName or visualized in the DevTools Performance panel. This approach works identically in development and production builds because the APIs are no‑ops when not supported, and it avoids adding extra logic to each middleware while still isolating synchronous middleware cost from reducer and listener work.