python
35 lines · 8 steps
Computing latency percentiles in Python
Two functions turn raw latency samples into interpolated percentiles and an SLO pass/fail check.
Explained by
highlit
1import bisect
2from typing import Sequence
3
4
5def percentile_latencies(
6 samples_ms: Sequence[float],
7 percentiles: Sequence[float] = (50, 90, 95, 99),
8) -> dict[str, float]:
9 if not samples_ms:
10 raise ValueError("cannot compute percentiles over an empty sample set")
11
12 ordered = sorted(samples_ms)
13 n = len(ordered)
14 results: dict[str, float] = {}
15
16 for p in percentiles:
17 if not 0 <= p <= 100:
18 raise ValueError(f"percentile {p} out of range [0, 100]")
19
20 rank = (p / 100) * (n - 1)
21 lower = int(rank)
22 upper = min(lower + 1, n - 1)
23 weight = rank - lower
24
25 value = ordered[lower] + (ordered[upper] - ordered[lower]) * weight
26 results[f"p{p:g}"] = round(value, 3)
27
28 return results
29
30
31def within_slo(samples_ms: Sequence[float], threshold_ms: float, target_p: float = 99) -> bool:
32 ordered = sorted(samples_ms)
33 idx = bisect.bisect_right(ordered, threshold_ms)
34 observed_p = 100 * idx / len(ordered)
35 return observed_p >= target_p
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Linear interpolation between neighboring ranks gives smoother percentile estimates than picking a single nearest sample.
- 2Sorting once up front lets every percentile lookup reduce to cheap index arithmetic.
- 3You can flip a latency question around: instead of the value at a percentile, ask what percentile a threshold falls at using binary search.
Related explainers
python
from flask import Blueprint, jsonify, request, abort v1 = Blueprint("users_v1", __name__) v2 = Blueprint("users_v2", __name__)
Versioning a Flask API with Blueprints
api versioning
blueprints
rest
Intermediate
7 steps
rust
use std::cmp::Ordering; pub struct PrefixIndex { entries: Vec<String>,
Prefix search with binary partitioning in Rust
binary-search
sorting
case-insensitive
Intermediate
7 steps
python
import time import threading from enum import Enum from functools import wraps
Building a circuit breaker in Python
circuit-breaker
resilience
decorators
Advanced
7 steps
python
from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector from django.core.cache import cache from django.db.models import F from django.http import JsonResponse
Ranked full-text search in Django
full-text-search
debouncing
caching
Advanced
9 steps
python
import os from datetime import timedelta
Class-based config in a Flask app factory
configuration
app-factory
inheritance
Intermediate
7 steps
python
import time from flask import Flask, g, request
Timing requests with Flask hooks
middleware
request-lifecycle
instrumentation
Intermediate
5 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/computing-latency-percentiles-in-python-explained-python-d10d/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.