Aller au contenu

Appliquez les lois opérationnelles

Pendant deux minutes du pic d’ouverture, l’équipe de la billetterie a relevé quelques compteurs : combien de temps le disque de la base de données a été occupé, combien d’accès il a servis, combien de commandes ont été validées. Rien de plus. Peut-on en déduire le temps que chaque commande passe sur le disque, ou le nombre de commandes en cours à chaque instant ?

Oui, et sans aucune hypothèse de probabilité ! Les lois opérationnelles sont des identités, vraies sur n’importe quelle période d’observation. Ce sont les outils les plus simples et les plus utiles de tout le cours.

Le modèle : des ressources que les requêtes visitent

Section intitulée « Le modèle : des ressources que les requêtes visitent »

On voit le système comme un ensemble de KK ressources (processeur, disques, réseau), que chaque requête visite une ou plusieurs fois avant de repartir. Pour la billetterie, une commande passe par le serveur web frontal, puis alterne entre le processeur du serveur d’application et le disque de la base de données.

arrivéesweb frontalprocesseurdisque BDDdépartsplusieurs allers-retours par commande

Sur une période d’observation de durée TT, on relève pour chaque ressource ii :

  • BiB_i : le temps occupé (busy time) de la ressource ;
  • AiA_i : le nombre d’arrivées (demandes de service) ;
  • CiC_i : le nombre de terminaisons (services achevés).

Pour le système entier, on note A0A_0 le nombre de requêtes entrées et C0C_0 le nombre de requêtes terminées. Ce sont des compteurs très faciles à obtenir : les outils système comme iostat ou vmstat les fournissent directement.

À partir de ces compteurs, on définit les variables dérivées :

VariableFormuleSignification
Temps de serviceSi=Bi/CiS_i = B_i / C_idurée moyenne d’un passage sur la ressource ii
UtilisationUi=Bi/TU_i = B_i / Tfraction du temps où ii est occupée
Débit de la ressourceXi=Ci/TX_i = C_i / Tpassages terminés par seconde sur ii
Taux d’arrivéeλi=Ai/T\lambda_i = A_i / Tdemandes arrivant par seconde sur ii
Débit du systèmeX0=C0/TX_0 = C_0 / Trequêtes terminées par seconde
Nombre de visitesVi=Ci/C0V_i = C_i / C_0nombre moyen de passages sur ii par requête
Demande de serviceDi=ViSiD_i = V_i S_itemps total de service reçu sur ii par requête

La dernière ligne est la plus importante du cours. La demande de service DiD_i est le temps qu’une requête passe réellement à se faire servir par la ressource ii, toutes visites confondues, sans compter l’attente.

Les trois premières lois : utilisation, flux forcé, demande de service

Section intitulée « Les trois premières lois : utilisation, flux forcé, demande de service »

On suppose l’équilibre des flux (job flow balance) : sur la période, il entre autant de requêtes qu’il en sort (Ai=CiA_i = C_i et A0=C0A_0 = C_0). C’est raisonnable dès que la période est longue devant le temps de réponse.

Loi d’utilisation. En écrivant Ui=Bi/T=(Ci/T)(Bi/Ci)U_i = B_i/T = (C_i/T)(B_i/C_i), on obtient :

Ui=Xi Si=λi SiU_i = X_i \, S_i = \lambda_i \, S_i

L’utilisation d’une ressource est son débit multiplié par son temps de service. La deuxième égalité vient de l’équilibre des flux (Xi=λiX_i = \lambda_i).

Loi du flux forcé (forced flow law). Chaque requête du système provoque en moyenne ViV_i passages sur ii, donc :

Xi=Vi X0X_i = V_i \, X_0

Le débit de chaque ressource est « forcé » par le débit du système. C’est ce qui permet de passer d’une ressource au système entier.

Loi de la demande de service. En combinant les deux précédentes :

Di=Vi Si=UiX0D_i = V_i \, S_i = \frac{U_i}{X_0}

C’est une formule précieuse en pratique : vous n’avez même pas besoin de compter les visites. L’utilisation de la ressource et le débit du système suffisent pour connaître la demande de service.

C’est la plus célèbre des lois de performance. Elle relie le nombre moyen de requêtes présentes dans un système NN, son débit XX et le temps de réponse moyen RR :

N=X RN = X \, R
  • NN est le nombre moyen de requêtes présentes (en attente ou en service) ;
  • XX est le débit (requêtes terminées par seconde) ;
  • RR est le temps moyen qu’une requête passe dans le système.

L’intuition est simple : si 10 commandes entrent chaque seconde et que chacune reste 0,2 s, alors à tout instant il y a en moyenne 10×0,2=210 \times 0{,}2 = 2 commandes en cours de traitement. Pensez à une file devant une boulangerie : si 2 clients arrivent par minute et que chacun reste 5 minutes, il y a en moyenne 10 clients dans la boutique.

0510nombre de requêtesséjour d’une requêteaire entre les courbes= somme des séjours = 16 sarrivées cumulées A(t)départs cumulés C(t)0246810temps (s), période d’observation T = 10 s0123N(t) = A − CN moyen = aire / T = 1,6X = C / T = 1 req/s ; R = aire / C = 1,6 s ; donc N = X × R = 1,6
L'aire entre arrivées et départs est à la fois la somme des temps de séjour (16 s) et l'intégrale du nombre de requêtes présentes : diviser par T donne N = 1,6, diviser par C donne R = 1,6 s, d'où N = X R.

La force de cette loi, c’est qu’elle s’applique à n’importe quel sous-système dont on sait délimiter les entrées et les sorties : une file d’attente seule, un disque (file comprise), le serveur entier, ou même un système avec ses utilisateurs.

Dans un système interactif, un nombre fixe MM d’utilisateurs alternent entre deux états : ils attendent une réponse (pendant RR), puis ils réfléchissent avant de cliquer à nouveau (pendant un temps de réflexion moyen ZZ). Appliquons Little à la boucle complète « utilisateurs plus système » : les MM utilisateurs sont tous quelque part dans la boucle, et chaque tour dure R+ZR + Z. Donc M=X0(R+Z)M = X_0 (R + Z), d’où :

R=MX0−ZR = \frac{M}{X_0} - Z
  • MM est le nombre d’utilisateurs connectés ;
  • X0X_0 est le débit du système ;
  • ZZ est le temps de réflexion moyen entre la réponse et la requête suivante.
utilisateurs qui réfléchissentZ = 15 s ; X₀ × Z = 150 personnesle systèmeR = 0,2 s ; X₀ × R = 2 requêtesclic : X₀ = 10 req/sréponseM = 150 + 2 = 152 utilisateurs = X₀ (R + Z)
Little appliquée à chaque moitié de la boucle : X₀ Z = 150 personnes réfléchissent et X₀ R = 2 requêtes sont en cours, soit bien les 152 utilisateurs connectés.

Les lois opérationnelles se codent en quelques lignes. C’est le genre de script que l’on garde sous la main pour vérifier la cohérence de mesures :

T, C0 = 120.0, 1_200 # durée d'observation (s), commandes terminées
compteurs = { # ressource : (temps occupé B en s, passages C)
"web": (24.0, 1_200),
"processeur": (36.0, 6_000),
"disque": (72.0, 4_800),
}
X0 = C0 / T
print(f"Débit du système X0 = {X0:.1f} req/s")
for nom, (B, C) in compteurs.items():
U = B / T # loi d'utilisation
S = B / C # temps de service par visite
V = C / C0 # visites par requête
D = U / X0 # loi de la demande de service (= V * S)
print(f"{nom:<11} U={U:.2f} S={S*1000:5.1f} ms V={V:.0f} D={D*1000:5.1f} ms")

La sortie donne une demande de 20 ms pour le serveur web, 30 ms pour le processeur et 60 ms pour le disque. Nous réutiliserons ces trois demandes dans tous les chapitres suivants.

01020304050607080temps de service reçu par commande (ms) ; chaque bloc est une visite de durée Sweb frontalprocesseurdisque BDD20D = 1 × 20 = 20 ms6D = 5 × 6 = 30 ms15D = 4 × 15 = 60 ms
Chaque bloc est une visite de durée S ; la demande D est la longueur totale de la barre. Le processeur a le plus de visites, mais c'est le disque qui a la plus grande demande (60 ms).
  • Les lois opérationnelles sont des identités tirées de compteurs (TT, BiB_i, AiA_i, CiC_i, C0C_0), sans hypothèse probabiliste ; on suppose seulement l’équilibre des flux.
  • Utilisation : Ui=XiSiU_i = X_i S_i. Flux forcé : Xi=ViX0X_i = V_i X_0.
  • Demande de service : Di=ViSi=Ui/X0D_i = V_i S_i = U_i / X_0, le temps de service total par requête sur la ressource ii.
  • Little : N=XRN = X R, valable pour tout sous-système délimité.
  • Temps de réponse interactif : R=M/X0−ZR = M / X_0 - Z, qui n’est autre que Little appliquée à la boucle utilisateurs plus système.
  • Ne confondez pas SiS_i (par visite) et DiD_i (par requête), ni le temps de service (sans attente) et le temps de réponse (avec attente).

Exercice · Du compteur à la demande

facile

Sur une période de 5 minutes, un serveur de fichiers a terminé 9 000 requêtes. Son disque a été occupé 180 s et a effectué 27 000 accès.

Calculez l’utilisation du disque, son débit, son temps de service, le nombre de visites par requête et la demande de service.

Voir la solution

T=300T = 300 s.

  • Utilisation : U=180/300=0,6U = 180/300 = 0{,}6.
  • Débit du disque : X=27 000/300=90X = 27\,000/300 = 90 accès/s.
  • Temps de service : S=180/27 000≈6,67S = 180/27\,000 \approx 6{,}67 ms.
  • Débit du système : X0=9 000/300=30X_0 = 9\,000/300 = 30 req/s, donc V=27 000/9 000=3V = 27\,000/9\,000 = 3 visites par requête.
  • Demande de service : D=VS=3×6,67=20D = V S = 3 \times 6{,}67 = 20 ms, que l’on retrouve par U/X0=0,6/30=0,02U/X_0 = 0{,}6/30 = 0{,}02 s.

En code

T = 5 * 60 # période d'observation (s)
C0, B, C = 9_000, 180, 27_000 # requêtes terminées, temps occupé du disque (s), accès disque
U = B / T # utilisation
X = C / T # débit du disque (accès/s)
S = B / C # temps de service par accès (s)
X0 = C0 / T # débit du système (req/s)
V = C / C0 # visites par requête
D = V * S # demande de service (s)
print(U, X, round(S * 1000, 2), X0, V) # 0.6 90.0 6.67 30.0 3.0
print(round(D * 1000, 1), U / X0) # 20.0 0.02 : les deux calculs de D concordent

Exercice · Little dans tous les sens

moyen
  1. Une file de messages reçoit 500 messages par seconde et en contient 1 500 en moyenne. Combien de temps un message y reste-t-il ?
  2. Un site a en moyenne 40 requêtes en cours et un temps de réponse moyen de 0,2 s. Quel est son débit ?
  3. Un pool de 32 fils d’exécution traite des requêtes qui durent 80 ms chacune, sans attente. Quel débit maximal peut-il soutenir ?
Voir la solution
  1. R=N/X=1 500/500=3R = N/X = 1\,500/500 = 3 s.
  2. X=N/R=40/0,2=200X = N/R = 40/0{,}2 = 200 req/s.
  3. Au maximum, les 32 fils sont tous occupés : N=32N = 32. Avec R=0,08R = 0{,}08 s, X=32/0,08=400X = 32/0{,}08 = 400 req/s. Au-delà, les requêtes supplémentaires devront attendre un fil libre, et le temps de réponse augmentera.

En code

# Loi de Little : N = X * R, on isole l'inconnue à chaque fois
R_file = 1_500 / 500 # 1. R = N / X
X_site = 40 / 0.2 # 2. X = N / R
X_pool = 32 / 0.080 # 3. X = N / R avec les 32 fils occupés
print(R_file, X_site, X_pool) # 3.0 s 200.0 req/s 400.0 req/s

Exercice · Un système interactif

difficile

Un logiciel de gestion est utilisé par 60 agents simultanés. On mesure un débit de 5 transactions/s et un temps de réponse moyen de 2 s. Le processeur du serveur a une utilisation de 0,5.

  1. Quel est le temps de réflexion moyen des agents ?
  2. Quelle est la demande de service du processeur ?
  3. Combien de transactions sont en moyenne présentes dans le serveur ? Et combien d’agents sont en train de réfléchir ?
Voir la solution
  1. De R=M/X0−ZR = M/X_0 - Z, on tire Z=M/X0−R=60/5−2=10Z = M/X_0 - R = 60/5 - 2 = 10 s.
  2. DCPU=U/X0=0,5/5=0,1D_{\text{CPU}} = U/X_0 = 0{,}5/5 = 0{,}1 s, soit 100 ms par transaction.
  3. Little sur le serveur seul : N=X0R=5×2=10N = X_0 R = 5 \times 2 = 10 transactions en cours. Little sur les agents en réflexion : NZ=X0Z=5×10=50N_Z = X_0 Z = 5 \times 10 = 50. On vérifie que 10+50=6010 + 50 = 60 : tous les agents sont bien comptés.

En code

M, X0, R, U_cpu = 60, 5, 2, 0.5 # agents, débit (tr/s), temps de réponse (s), utilisation CPU
Z = M / X0 - R # 1. loi du temps de réponse interactif
D_cpu = U_cpu / X0 # 2. loi de la demande de service
N_serveur = X0 * R # 3. Little sur le serveur
N_reflexion = X0 * Z # Little sur les agents qui réfléchissent
print(Z, D_cpu) # 10.0 s 0.1 s
print(N_serveur, N_reflexion, N_serveur + N_reflexion) # 10 50 60 : tout le monde est compté