Use median to summarize skewed durations
Also published in our Blogger archive.
A single unusually long run can make an arithmetic mean unrepresentative of the middle of a small set of durations. statistics.median() returns the middle value of numeric data after ordering it; with an odd number of observations, that is the central observation. The statistics module is part of the Python standard library.
The synthetic durations in this example are 18, 19, 20, 21, and 120 milliseconds. Four observations cluster around 20 ms, while one slow run pulls the mean to 39.6 ms. The median remains 20 ms, which is a useful description of the middle observation in this particular sample. Assertions verify both computed values before the program prints them. Keeping the mean in the output makes the effect of the outlying input visible rather than implying that median is universally preferable.
Median is not a diagnosis of a performance issue and it does not tell you the tail latency, distribution shape, sample size adequacy, or whether the measurements were collected consistently. For latency reporting, a percentile may better answer a service-level question; for a symmetric distribution, a mean can still be informative. statistics.median() raises StatisticsError for empty data, so production code should define its empty-input policy. The input values should also use consistent units before any summary is calculated.
The official statistics.median documentation explains its behavior for ordered numeric data.
AI assistance disclosure: This article was drafted with AI assistance and should be reviewed for the intended performance-reporting policy.
from statistics import mean, median
durations_ms = [18, 19, 20, 21, 120]
typical_duration = median(durations_ms)
average_duration = mean(durations_ms)
assert typical_duration == 20
assert average_duration == 39.6
print(f"median duration: {typical_duration} ms")
print(f"mean duration: {average_duration} ms")
median duration: 20 ms
mean duration: 39.6 ms