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.

Easy Python 3.9+ Aug 9, 2026 Observability & SRE 13 views 0 copies

Python code

31 lines
Python 3.9+
import 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

stdout
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

  1. Use `numpy.percentile(data, [50, 90, 95, 99])` for faster computation on large arrays
  2. 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

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Observability & SRE

Related tutorials and quizzes for this topic.