Scrie benchmark-uri pentru codul critic și rulează-le în CI

Subiect din roadmap-ul Bune practici: performanța backend · parte din „Măsurare și profilare”

Această practică implică crearea de teste automate care măsoară performanța codului considerat critic (de exemplu, algoritmi complecși sau endpoint-uri API des folosite) și integrarea lor în pipeline-ul de integrare continuă (CI). Este esențială pentru a preveni regresiile de performanță care pot scădea treptat viteza aplicației, afectând experiența utilizatorilor și costurile de infrastructură. Dacă ignori acest aspect, riscă să introdugi accidental cod ineficient în producție, descoperind problema abia când utilizatorii se plâng de latență ridicată.

Cum o aplici

  1. Identifică codul critic: Analizează profilarea existentă sau datele de producție pentru a găsi funcțiile care consumă cel mai mult timp CPU sau memorie.
  2. Scrie benchmark-uri unitare: Folosește framework-ul de benchmarking al limbajului tău pentru a măsura timpul de execuție sau allocările de memorie ale funcțiilor identificate.
  3. Stabilește praguri (thresholds): Definește o valoare maximă acceptabilă pentru timp sau memorie, bazată pe versiunea curentă stabilă.
  4. Integrează în CI: Adaugă rularea acestor benchmark-uri în pipeline-ul tău de CI (ex: GitHub Actions, GitLab CI), asigurându-te că testul eșuează dacă performanța scade sub pragul stabilit.

Exemplu

Să presupunem că ai o funcție de sortare în Python.

Varianta greșită (test funcțional simplu):

def test_sort():
    assert sort([3, 1, 2]) == [1, 2, 3]

Acest test verifică corectitudinea, dar nu detectează dacă ai înlocuit algoritmul O(n log n) cu unul O(n^2).

Varianta corectă (benchmark cu pytest-benchmark):

def test_sort_performance(benchmark):
    data = list(range(1000))
    # Benchmark-ul va rula funcția de multe ori și va calcula media
    result = benchmark(sort, data)
    assert result == sorted(data)

În configurarea CI, poți seta un prag: dacă timpul mediu crește cu peste 10% față de branch-ul principal, build-ul eșuează.

Cum verifici

Verifici aplicarea prin rapoartele generate de tool-ul de benchmarking în jurnalul de build al CI. Caută metrici precum mean time, stddev și compară-le cu valoarea de referință (baseline). Unele framework-uri permit generarea de grafice istorice pentru a vizualiza tendințele pe termen lung. De asemenea, poți verifica dacă testul este marcat ca critical sau blocker în pipeline, astfel încât orice degradare semnificativă să blocheze merge-ul codului.

Greșeli frecvente

  • Benchmark-uri instabile: Rularea pe mașini virtuale cu resurse partajate poate duce la rezultate zgomotoase. Asigură-te că mediul CI este izolat și dedicat.
  • Ignorarea overhead-ului: Nu include setup-ul datelor în măsurătoare dacă acesta nu face parte din logica critică, sau viceversa, în funcție de ce vrei să optimizezi.
  • Praguri prea stricte: Setarea unor limite imposibil de menținut duce la „alert fatigue” și la dezactivarea testelor. Ajustează pragurile periodic pe baza evoluției hardware-ului și a optimizărilor reale.

Alte subiecte din „Măsurare și profilare”