How to Calculate Percentile Latency in Python
Generate mock latency samples with occasional spikes and compute 50th, 90th, 95th, and 99th percentile values in milliseconds.
Python code
31 linesimport random
import statistics
def generate_latency_samples(n=1000):
"""Generate realistic mock latency data (ms) with occasional spikes."""
samples = []
for _ in range(n):
# Normal case: ~50ms with jitter
base = random.gauss(50, 5)
# 2% spike chance: slow downstream or GC pause
if random.random() < 0.02:
base += random.uniform(100, 500)
samples.append(max(0, base))
return samples
def percentile(data, p):
"""Compute p-th percentile of a list."""
sorted_data = sorted(data)
k = (len(sorted_data) - 1) * (p / 100)
f = int(k)
c = f + 1
if c >= len(sorted_data):
return sorted_data[f]
return sorted_data[f] + (k - f) * (sorted_data[c] - sorted_data[f])
if __name__ == "__main__":
random.seed(42)
latencies = generate_latency_samples()
for p in (50, 90, 95, 99):
print(f"p{p}: {percentile(latencies, p):.2f} ms")
print(f"mean: {statistics.mean(latencies):.2f} ms")
Output
p50: 50.05 ms
p90: 54.52 ms
p95: 56.77 ms
p99: 99.09 ms
mean: 51.87 ms
How it works
The generate_latency_samples function uses random.gauss to create normal jitter around 50 ms, then adds a larger random spike 2% of the time to simulate slow downstream calls or GC pauses. The percentile function sorts the data and interpolates between the two nearest ranks using the formula (n-1) * p / 100, which matches the numpy.percentile default linear method. The if __name__ == "__main__" guard keeps the demo runnable as a script while staying importable. Setting random.seed(42) makes the output reproducible across runs.
Common mistakes
- Using `round` instead of interpolation, which discards fractional percentile precision
- Forgetting to sort the data before calculating the percentile
- Not handling empty lists, which raises a division-by-zero error in the index formula
- Confusing p50 with the mean — they differ significantly when spikes skew the distribution
Variations
- Use `numpy.percentile(data, [50, 90, 95, 99])` for faster computation on large arrays
- Use `statistics.quantiles(data, n=100)` for a simpler API in Python 3.8+
Real-world use cases
- Monitoring API response times to flag SLO breaches when p99 crosses the target threshold.
- Analyzing batch job durations to distinguish normal variation from rare slow outliers.
- Tuning database query performance by tracking p95 latency across different index configurations.
Sponsored
More from Observability & SRE
- Adding a Correlation ID to Log Context in Python medium
- Calculate Error Rate from Log Stream in Python easy
- Check if a Timestamp Falls in a Daily Maintenance Window in Python easy
- Export Metrics with OTLP Mock in Python medium
- Generate Mock CPU and Memory Metrics in Python easy
- Generate Prometheus Text Exposition Format in Python easy
Keep learning
Related tutorials and quizzes for this topic.