Latence P95 et P99 : définition et mesure

Rene, Kabir Goel 
Latence P95 et P99 : définition et mesure

La latence P99 est le temps de réponse battu par 99 % des requêtes. Si le P99 d’une API est de 400 millisecondes, 99 requêtes sur cent reviennent en 400 ms ou moins, et une prend plus longtemps. Le P95 applique la même idée à 95 % : une requête sur vingt est plus lente. Les deux décrivent la traîne de la distribution, les requêtes lentes qu’une moyenne lisse.

La traîne compte plus que sa taille ne le laisse penser. Quelqu’un qui fait une seule requête la remarque rarement. Quelqu’un qui parle vingt tours avec un agent vocal la remarquera probablement. Ce guide explique comment fonctionnent les percentiles, comment les calculer, les erreurs qui les faussent et ce qu’ils signifient pour l’IA vocale en temps réel.

P50, P95 et P99 en un coup d’œil

PercentileCe qu’il indiqueRequêtes plus lentes
P50La médiane, une requête typique1 sur 2
P90Le début de la traîne lente1 sur 10
P95La cible habituelle des tableaux de bord et SLO1 sur 20
P99Ralentissements rares : pauses, reprises, files1 sur 100
P99.9Cas isolés visibles seulement à fort volume1 sur 1 000

Les percentiles élevés demandent plus d’échantillons pour avoir un sens. Un P99 calculé sur 100 requêtes repose sur une seule d’entre elles. Visez au moins quelques centaines d’échantillons pour le P95 et quelques milliers pour le P99, et affichez le nombre d’échantillons à côté du résultat.

Pourquoi la moyenne cache la traîne

Prenez 100 requêtes. 94 se terminent en 200 ms et 6 prennent deux secondes. La moyenne est de 308 ms, une durée qu’aucune requête n’a eue. La médiane est de 200 ms, ce qui semble excellent. Le P95 et le P99 valent 2 000 ms : c’est ce qu’ont vécu six de vos utilisateurs.

Les vraies distributions de latence sont déséquilibrées de cette façon. La plupart des requêtes empruntent le chemin rapide, et une minorité attend derrière un disque lent, un cache froid, une pause du ramasse-miettes ou une file pleine. La moyenne mélange les deux groupes en un chiffre qui ne décrit aucun des deux. La médiane ignore complètement le groupe lent. Les percentiles le gardent visible.

Comment calculer P95 et P99

Triez les mesures de la plus rapide à la plus lente et lisez la valeur située à 95 % ou 99 % de la liste. Avec 200 échantillons, le P95 est la 190e valeur et le P99 la 198e. C’est la méthode du rang le plus proche :

import math


def percentile(samples, p):
    """Nearest rank: the smallest sample with at least p% of samples at or below it."""
    ordered = sorted(samples)
    rank = math.ceil(p / 100 * len(ordered))
    return ordered[max(rank, 1) - 1]


latencies_ms = [200] * 94 + [2000] * 6
print(percentile(latencies_ms, 50))  # 200
print(percentile(latencies_ms, 95))  # 2000
print(percentile(latencies_ms, 99))  # 2000

NumPy interpole par défaut, donc numpy.percentile peut renvoyer une valeur située entre deux échantillons. Passez method="inverted_cdf" pour obtenir le rang le plus proche. Sur peu d’échantillons, les deux méthodes peuvent nettement diverger, une raison de plus d’indiquer le nombre d’échantillons.

Les systèmes de supervision ne conservent généralement pas chaque échantillon. Ils comptent les requêtes par tranches de latence et estiment le percentile à partir de l’histogramme, comme le fait histogram_quantile() de Prometheus. L’estimation n’est pas plus précise que les tranches qui l’entourent : placez les limites près des latences qui vous intéressent.

Trois erreurs qui faussent les percentiles

Faire la moyenne des percentiles. Un serveur traite 900 requêtes, toutes en 200 ms, et un second en traite 100, dont dix prennent une seconde. Les P95 sont de 200 ms et 1 000 ms, et leur moyenne de 600 ms. Le vrai P95 sur les 1 000 requêtes est de 200 ms. La documentation de Prometheus le dit aussi : des quantiles calculés séparément ne s’agrègent pas. Fusionnez les histogrammes ou les échantillons, puis calculez.

Additionner les percentiles des étapes. Un agent vocal enchaîne reconnaissance vocale, modèle de langage et synthèse vocale. Supposons que la reconnaissance prenne toujours 300 ms, que le LLM prenne 500 ms mais 1 500 ms un appel sur dix, et que le TTS prenne 150 ms mais 600 ms un appel sur dix. Additionner les P95 des étapes donne 2 400 ms. Le vrai P95 du tour complet est de 1 950 ms, car les deux cas lents tombent rarement sur le même tour. Mesurez directement le temps de bout en bout au lieu de l’estimer à partir des parties.

Mesurer avec un client qui attend. Un générateur de charge qui n’envoie la requête suivante qu’au retour de la précédente envoie moins de requêtes précisément quand le serveur ralentit : les périodes lentes sont sous-représentées. Gil Tene appelle cela l’omission coordonnée, et son générateur de charge wrk2 l’évite en envoyant à débit fixe. Pour des chiffres de production, mesurez le trafic réel plutôt qu’un client de test.

Pourquoi la traîne décide du ressenti d’un agent vocal

La conversation obéit à un timing serré. Une revue de la recherche sur les tours de parole de Levinson et Torreira établit que les silences entre tours sont de l’ordre de 200 ms. Dans une étude d’appels téléphoniques, Kendrick et Torreira ont constaté qu’après un silence de plus de 700 ms environ, les réponses étaient surtout des refus et d’autres réponses non préférées, et que même un silence de plus de 300 ms environ rendait une acceptation franche moins probable. L’auditeur donne un sens aux pauses : pour un appelant, un agent qui se tait 900 ms peut paraître réticent, pas seulement lent.

Multipliez maintenant par le nombre de tours. Si chaque tour a, indépendamment, 5 % de chances de dépasser le P95, un appel de 20 tours a 64 % de chances d’en rencontrer au moins un (1 − 0,95²⁰). Même le P99 apparaît dans environ 18 % des appels de 20 tours. La médiane décrit un tour typique ; la traîne décrit un appel typique. Jeff Dean et Luiz André Barroso, chez Google, ont fait la même observation pour les grands services dans The Tail at Scale : quand une action d’utilisateur se répartit en nombreuses requêtes, les réponses lentes rares deviennent courantes.

Que mesurer dans une chaîne vocale

Mesurez ce que l’appelant entend. Pour un agent vocal, c’est le temps entre la fin de sa phrase et le premier échantillon audible de la réponse, enregistré du côté de l’appelant. Découpez-le ensuite par étape pour savoir d’où vient la traîne :

ÉtapeCe qu’il faut chronométrerCauses fréquentes de traîne
Détection de fin de tourDe la fin de la parole à la fin du tour déclaréeHésitations, bruit de fond, longues pauses
Reconnaissance vocaleDe la fin du tour à la transcription finaleTours longs, gigue réseau
LLM et outilsDe la transcription au premier jeton, outils comprisOutils lents, longs prompts, files du fournisseur
Synthèse vocaleDu premier texte envoyé au premier son audibleNouvelles connexions, longues premières phrases
Réseau et téléphonieDe l’audio quittant votre serveur à l’appelantRoutage opérateur, tampons de gigue

Le temps jusqu’au premier son (TTFA) est l’indicateur de synthèse vocale à suivre, car un modèle en streaming commence la lecture avant que la phrase soit terminée. Le silence initial compte aussi : un fragment qui commence par 300 ms de silence, ce sont 300 ms d’attente en plus. Le script ci-dessous chronomètre les premiers octets : vérifiez donc séparément le silence initial de votre audio.

Ce script mesure les percentiles de TTFA de la synthèse vocale Sonic de Cartesia. Il planifie 205 requêtes à une demi-seconde d’intervalle, ignore les cinq premières et chronomètre chacune depuis son heure prévue jusqu’aux premiers octets audio. Mesurer depuis l’heure prévue plutôt que depuis l’envoi fait apparaître dans les chiffres une réponse lente qui retarde la requête suivante, ce qui évite l’omission coordonnée décrite plus haut :

import math
import os
import time

from cartesia import Cartesia


def percentile(samples, p):
    """Nearest rank: the smallest sample with at least p% of samples at or below it."""
    ordered = sorted(samples)
    rank = math.ceil(p / 100 * len(ordered))
    return ordered[max(rank, 1) - 1]


# max_retries=0: a retried request would hide a failure inside a slow sample.
client = Cartesia(api_key=os.environ["CARTESIA_API_KEY"], max_retries=0)
interval = 0.5  # seconds between scheduled requests
ttfa_ms = []
failures = 0
first = time.perf_counter() + interval

for i in range(205):
    # Each request has a fixed start time. If a slow response makes us late,
    # the wait counts against latency instead of quietly thinning the sample.
    scheduled = first + i * interval
    time.sleep(max(0.0, scheduled - time.perf_counter()))
    got_audio = False
    try:
        with client.tts.with_streaming_response.generate(
            model_id="sonic-3.6",
            transcript="Your order shipped this morning and should arrive on Thursday.",
            voice="6ccbfb76-1fc6-48f7-b71d-91ac6298247b",
            output_format={"container": "raw", "encoding": "pcm_s16le", "sample_rate": 16000},
            language="en",
        ) as response:
            for chunk in response.iter_bytes():
                if chunk:
                    got_audio = True
                    if i >= 5:  # the first requests pay for connection setup
                        ttfa_ms.append((time.perf_counter() - scheduled) * 1000)
                    break
    except Exception:
        pass
    if not got_audio:
        failures += 1

print(f"{len(ttfa_ms)} timed requests, {failures} failed or returned no audio")
if ttfa_ms:
    for p in (50, 90, 95, 99):
        print(f"p{p}: {percentile(ttfa_ms, p):.0f} ms")
    print(f"max: {max(ttfa_ms):.0f} ms")

Installez le SDK avec pip install cartesia et définissez CARTESIA_API_KEY depuis le tableau de bord. Lancez-le depuis la région où tournent vos serveurs, à l’heure de pointe de votre trafic : un ordinateur portable sur le Wi-Fi de la maison mesure le Wi-Fi. Le SDK relance par défaut deux fois les requêtes en échec, ce qui fondrait un échec et sa reprise en un seul échantillon lent ; le script désactive donc les reprises et compte à part les échecs, y compris les réponses sans audio. Ne les retirez pas du rapport : une requête qui n’a jamais répondu est la pire latence qui soit. Pour un agent en direct, chronométrez le chemin WebSocket que vous utilisez réellement, puisqu’il garde une connexion ouverte d’un tour à l’autre.

Ce que montrent les benchmarks publics

Coval exécute toutes les 30 minutes des benchmarks indépendants de synthèse vocale, de reconnaissance vocale et de parole à parole sur des API publiques, et publie médianes, percentiles et nombres d’échantillons. Sa méthodologie inclut le silence initial dans le TTFA et exclut l’établissement des connexions.

Sur son classement de synthèse vocale à 30 jours, consulté le 15 octobre 2026, l’écart entre médiane et P95 variait fortement entre 33 modèles comptant chacun au moins 260 échantillons. Pour le modèle typique, le P95 valait 1,38 fois la médiane. Aux extrêmes, le P95 d’un modèle valait 1,1 fois sa médiane, et celui d’un autre plus de sept fois : 624 ms en temps typique, 4 751 ms pour une requête sur vingt.

La leçon est celle du début de ce guide : deux modèles aux médianes proches peuvent donner des appels très différents. Comparez les P95, avec le nombre d’échantillons, mesurés comme vos utilisateurs les vivent.

Réduire la latence de traîne

  • Gardez les connexions ouvertes. Chaque nouvelle requête HTTPS repaie l’établissement TCP et TLS, et la documentation de Cartesia note que ce coût est souvent du même ordre que le temps jusqu’au premier octet audio. Un WebSocket ouvert pendant tout l’appel ne le paie qu’une fois.
  • Mettez en cache ce qui se répète. Les salutations, les messages d’attente et les formules de fin n’ont pas besoin d’être générés à chaque appel. Mettez-les en cache en audio brut et insérez-les dans le flux en direct.
  • Commencez à parler plus tôt. Envoyez les jetons du LLM à la synthèse vocale dès leur arrivée au lieu d’attendre un paragraphe entier.
  • Fixez un délai aux outils. Un appel d’outil qui prend deux secondes ajoute deux secondes au tour, à chaque fois. Fixez un délai maximal et faites dire à l’agent ce qu’il fait pendant l’attente.
  • Doublez les requêtes lentes. The Tail at Scale décrit l’envoi d’une requête de secours quand la première dépasse le P95 habituel, en gardant la première réponse reçue. Attendre le P95 limite la charge supplémentaire à environ 5 %. Ne le faites qu’avec des requêtes sans risque en double, comme régénérer le même audio, jamais avec un outil qui écrit des données.
  • Rapprochez les modèles de l’appel. Si votre traîne vient de la distance réseau ou d’une infrastructure partagée, le déploiement sur site installe les modèles à côté de votre téléphonie.

Si vous préférez ne pas assembler et régler la chaîne vous-même, Cartesia Managed Agents exécute la détection de fin de tour, la reconnaissance vocale Ink, le LLM et Sonic sur un numéro de téléphone, et vous pouvez en créer un dans le playground et l’appeler. Si votre propre chaîne est lente, la solution se trouve en général dans l’étape que désignent vos mesures, et le script ci-dessus est le point de départ.

Guides associés

FAQ

Qu'est-ce que la latence P99 ?

La latence P99 est le 99e percentile des temps de réponse : 99 % des requêtes se terminent en ce temps ou moins, et le 1 % le plus lent prend plus longtemps. Si le P99 d'une API est de 400 ms, une requête sur cent dépasse 400 ms. Il décrit l'extrémité lente de la distribution, celle qu'une moyenne masque.

Qu'est-ce que la latence P95 ?

La latence P95 est le temps de réponse atteint ou battu par 95 % des requêtes. Une requête sur vingt est plus lente. C'est le percentile que la plupart des équipes affichent dans leurs tableaux de bord et leurs objectifs de niveau de service, car il suit les vrais problèmes sans dépendre de quelques cas isolés.

Quelle différence entre P95 et P99 ?

P95 correspond aux 5 % de requêtes les plus lentes ; P99, au 1 % le plus lent. P95 reflète le comportement du système en charge normale. P99 dépend plutôt d'événements ponctuels : pauses du ramasse-miettes, caches froids, nouvelles tentatives, files d'attente. Publiez les deux avec la médiane, et indiquez le nombre d'échantillons.

Qu'est-ce que la latence de traîne ?

La latence de traîne est l'extrémité lente d'une distribution de latences, en général tout ce qui se situe à partir du P95. Le nom vient de la longue traîne à droite de l'histogramme. Dans les systèmes qui font de nombreuses requêtes par action, ou de nombreux tours par conversation, c'est la traîne que la plupart des utilisateurs finissent par rencontrer.

Peut-on faire la moyenne de valeurs P95 ?

Non. Le percentile d'un ensemble combiné de requêtes n'est pas la moyenne des percentiles de chaque partie, et le P95 d'une chaîne de traitement n'est pas la somme des P95 de chaque étape. Conservez les échantillons bruts ou les histogrammes, fusionnez-les et calculez le percentile sur les données fusionnées.

Quelle latence P95 faut-il à un agent vocal ?

Mesurez du moment où l'appelant cesse de parler au premier son qu'il entend. D'après la recherche sur la conversation, on se passe la parole en environ 200 ms, les silences de plus de 300 ms environ rendent un oui franc moins probable, et ceux de plus de 700 ms environ sont associés aux refus et autres réponses non préférées. Un agent vocal dont le P95 approche la seconde paraît hésitant un tour sur vingt.