Azimjon Abdurasulov

QA 23: Performance testing — Load, Stress, Spike, Soak va k6 bilan amaliyot

🧪 QA Engineer — Zero to Hero

QA 23: Performance testing — Load, Stress, Spike, Soak va k6 bilan amaliyot

Holat: 2026-yil oktabr. Dars Grafana k6 ning v2 qatori (eng so'nggi reliz — v2.3.0, 2026-yil 21-sentabr) va rasmiy k6 hujjatlari asosida yozilgan. Amaliy nishon — Grafana'ning o'quv ilovasi QuickPizza. Barcha raqamli chegaralar (Core Web Vitals, Apdex) manbalar bilan berilgan.

Bu darsdan keyin siz: performance testni "tugmani bosib RPS'ni ko'rish" emas, balki muhandislik jarayoni sifatida bajara olasiz:

  • latency, percentile (p95/p99), throughput va xato ulushini to'g'ri o'qiysiz;
  • smoke, load, stress, spike, soak va breakpoint testlarini farqlab, vaziyatga mosini tanlaysiz;
  • k6'da stages, thresholds, scenarios, custom metrikalar va test data bilan skript yozasiz;
  • natijani tahlil qilib, jamoaga tushunarli hisobot yozasiz;
  • frontend (Core Web Vitals) va mobil performance asoslarini bilasiz.

Mundarija

  1. Performance testing nima va nega kerak
  2. Asosiy metrikalar: latency, percentile, throughput, xatolar
  3. Little's Law va Apdex
  4. Test turlari: smoke, load, stress, spike, soak, breakpoint
  5. Jarayon: SLO'dan hisobotgacha
  6. k6 bilan tanishuv: o'rnatish va birinchi skript
  7. k6 chuqurroq: checks, thresholds, scenarios, metrikalar, data
  8. Natijani o'qish, hisobot va CI
  9. Boshqa vositalar: JMeter, Gatling, Locust
  10. Frontend va mobil performance
  11. Etika va xavfsizlik qoidalari
  12. Amaliy mashqlar
  13. O'zingizni tekshiring
  14. Xulosa
  15. Manbalar

1. Performance testing nima va nega kerak {#nima-uchun}

Performance testing — tizim yuklama ostida qanchalik tez, barqaror va kengayuvchan (scalable) ishlashini tekshiradigan non-functional testlash turi. Funksional test "ishlaydimi?" deb so'raydi, performance test esa "ko'p odam bir vaqtda ishlatganda ham yetarlicha tez va xatosiz ishlaydimi?" deb so'raydi.

Savol turiFunksional testPerformance test
Misol"Buyurtma berish tugmasi buyurtma yaratadimi?""Bir daqiqada 600 ta buyurtma kelsa, 95% so'rov 1 soniyadan tez javob oladimi?"
NatijaO'tdi / O'tmadiRaqamlar: p95, RPS, xato ulushi, CPU, xotira
QayerdaHar qanday muhitProd'ga o'xshash, alohida muhit

DemoBozor misoli. Aksiya kuni soat 20:00 da barcha mijozlarga push yuboriladi: "Choynaklarga −30%". 2–3 daqiqa ichida trafik odatdagidan bir necha baravar oshadi. Nima sinishi mumkin?

  • ma'lumotlar bazasi ulanishlari (connection pool) tugab qoladi → 500 va 503 xatolar;
  • kesh bo'sh bo'lsa, hamma so'rov bir vaqtda bazaga uriladi (cache stampede);
  • SMS (OTP) xizmati sekundiga cheklangan miqdordagi xabarni qabul qiladi → login "osilib" qoladi;
  • to'lov provayderiga so'rovlar timeout bo'ladi → buyurtma PENDING_PAYMENT holatida qotib qoladi.

Bularni funksional testlar topmaydi — har bir so'rov alohida olinganda "to'g'ri" ishlaydi.

QA'ning roli. Performance testni ko'pincha QA, DevOps/SRE va dasturchilar birga qiladi. QA odatda: talablarni (NFR — non-functional requirements) aniqlashtiradi, yuklama modelini loyihalaydi, skript yozadi, natijani tahlil qilib hisobot beradi. Server ichidagi sababni topish (profiling) — ko'proq dasturchi/SRE ishi.

🎯 Intervyuda: Load test va stress test farqi nima? — Load test kutilgan (o'rtacha yoki cho'qqi) yuklamada SLO bajarilishini tekshiradi; stress test yuklamani kutilganidan yuqoriga olib chiqib, tizim qayerda va qanday buzilishini hamda keyin tiklanishini o'rganadi.


2. Asosiy metrikalar: latency, percentile, throughput, xatolar {#metrikalar}

Response time (latency) qanday tuzilgan

Bitta HTTP so'rov vaqti bir necha bo'lakdan iborat. k6 ularning har birini alohida o'lchaydi:

Bosqichk6 metrikasiMa'nosi
Navbatda kutishhttp_req_blockedBo'sh TCP ulanish kutilgan vaqt
TCP ulanishhttp_req_connectingServerga ulanish
TLShttp_req_tls_handshakingHTTPS "qo'l berib ko'rishish"
Yuborishhttp_req_sendingSo'rov tanasini yuborish
Kutish (TTFB)http_req_waitingServer javobining birinchi baytigacha
Qabul qilishhttp_req_receivingJavobni to'liq yuklab olish
Jamihttp_req_durationsending + waiting + receiving (DNS va ulanishsiz)

🧠 Esda tuting: http_req_waiting (TTFB) katta bo'lsa — muammo odatda serverda (kod, baza, tashqi servis). http_req_receiving katta bo'lsa — javob juda og'ir (masalan, siqilmagan 5 MB JSON) yoki tarmoq sekin.

O'rtacha qiymat nega aldaydi: percentile'lar

10 ta so'rov javob vaqti (ms): 120, 130, 125, 140, 135, 128, 132, 3000, 138, 127.

  • O'rtacha (avg) = 4175 / 10 = 417.5 ms. Lekin hech bir foydalanuvchi 417 ms ni ko'rmadi: 9 kishi ~130 ms, bittasi esa 3 soniya kutdi.
  • Mediana (p50) = 131 ms — "odatiy" foydalanuvchi tajribasi.
  • p95 — so'rovlarning 95% shu qiymatdan tez. Ko'p namunali testda p95/p99 aynan "eng sekin 5% / 1%" foydalanuvchilarni ko'rsatadi.

Shuning uchun SLO'lar deyarli doim percentile bilan yoziladi: "GET /products uchun p95 < 500 ms", "o'rtacha < 300 ms" emas.

⚠️ Diqqat: Juda tez 500 xatolar o'rtacha va p95 ni "chiroyli" qilib ko'rsatishi mumkin. Shuning uchun latency'ni har doim xato ulushi bilan birga baholang.

Throughput, concurrency va xatolar

MetrikaMa'nosiDemoBozor SLO misoli
Throughput (http_reqs, RPS)Sekundiga bajarilgan so'rovlarAksiya soatida 300 RPS ko'tara olishi kerak
Iteratsiya tezligi (iterations)Sekundiga to'liq ssenariylar (masalan, "katalog → savatcha")—
Concurrency (vus)Bir vaqtdagi virtual foydalanuvchilar500 VU
Xato ulushi (http_req_failed)Muvaffaqiyatsiz so'rovlar foizi< 1%
ResurslarCPU, xotira, DB ulanishlari, navbat uzunligiCPU < 75%, DB pool < 80%

k6'da http_req_failed — kutilgan javob kodlariga mos kelmagan so'rovlar ulushi (k6 hujjatiga ko'ra bu setResponseCallback bilan belgilanadi). Server tomonidagi resurslarni k6 o'lchamaydi — ular uchun monitoring kerak (Grafana, Prometheus, Datadog va h.k.; batafsil: DevOps: Observability).

Ochiq va yopiq yuklama modeli

  • Yopiq model (closed) — VU'lar soni belgilanadi. Server sekinlashsa, har VU kamroq so'rov yuboradi → yuklama o'z-o'zidan kamayadi. Bu real hayotda ko'pincha muammoni yashiradi.
  • Ochiq model (open) — sekundiga yangi kelayotgan iteratsiyalar soni belgilanadi (arrival rate). Server sekinlashsa ham yangi "foydalanuvchilar" kelaveradi — xuddi aksiya kunidagidek.

k6'da yopiq model — constant-vus, ramping-vus; ochiq model — constant-arrival-rate, ramping-arrival-rate executor'lari (7-bo'lim).


3. Little's Law va Apdex {#littles-law}

Little's Law: nechta VU kerak?

Navbat nazariyasidagi oddiy, lekin kuchli formula:

L = λ × W

L — tizimdagi bir vaqtdagi "mijozlar" soni (concurrency)
λ — kelish tezligi (sekundiga so'rov yoki iteratsiya)
W — bitta mijozning tizimda o'tkazgan o'rtacha vaqti (soniya)

Misol 1 (API darajasi). DemoBozor API'ga cho'qqida 50 so'rov/s keladi, o'rtacha javob 0.4 s. Demak bir vaqtda o'rtacha 50 × 0.4 = 20 ta so'rov "ichkarida" bo'ladi. Server 20 ta parallel so'rovni ko'tara olmasa — navbat paydo bo'ladi va latency o'sadi.

Misol 2 (VU sonini hisoblash). Analitikaga ko'ra aksiya soatida 18 000 ta "katalog → mahsulot → savatcha" ssenariysi bajariladi: λ = 18 000 / 3600 = 5 iteratsiya/s. Bitta iteratsiya (so'rovlar + foydalanuvchining o'ylash vaqti sleep) o'rtacha 12 s davom etadi. U holda kerakli VU soni: L = 5 × 12 = 60 VU.

💡 Maslahat: sleep() (think time) qo'ymasangiz, 60 VU real 60 foydalanuvchidan ko'ra ancha ko'p so'rov yuboradi va natija real hayotga o'xshamaydi. Think time qiymatini analitikadan oling (sahifalar orasidagi o'rtacha vaqt).

Apdex: bitta raqamda "foydalanuvchi mamnunmi?"

Apdex (Application Performance Index) — 0 dan 1 gacha ball. Chegara T tanlanadi (masalan, 500 ms):

  • mamnun (satisfied): javob ≤ T;
  • chidaydigan (tolerating): T < javob ≤ 4T;
  • norozi (frustrated): javob > 4T.
Apdex_T = (mamnunlar + chidaydiganlar / 2) / jami namunalar

Misol. T = 500 ms, 1000 so'rov: 850 tasi ≤ 0.5 s, 100 tasi 0.5–2 s oralig'ida, 50 tasi > 2 s. Apdex = (850 + 100/2) / 1000 = 0.90.

Apdex rahbariyatga tushuntirish uchun qulay, lekin muhandislik qarorlarini baribir percentile va xato ulushiga qarab qabul qiling.


4. Test turlari: smoke, load, stress, spike, soak, breakpoint {#test-turlari}

k6 yuklama profillari: smoke, average-load, stress, spike, soak va breakpoint testlari

k6 hujjatidagi "test turlari" jadvali asosida (moslashtirildi):

TurVU / throughputDavomiyligiQachonDemoBozor misoli
SmokePastQisqa (soniya–daqiqa)Skript yoki kod o'zgarganda2 VU × 30 s: skript va muhit ishlayaptimi?
Average-loadOdatiy prod darajasiO'rta (5–60 daq)Muntazam: odatiy kunda SLO bajariladimi?Kunlik o'rtacha trafik × 30 daq
StressO'rtachadan yuqoriO'rta (5–60 daq)Yuqori yuklama kutilgandaAksiya prognozi × 1.5
SpikeJuda yuqori, keskinQisqa (bir necha daq)Mavsumiy aksiya, push, reklama20:00 push'dan keyingi sakrash
SoakO'rtachaUzoq (soatlar)Uzoq ishlashdagi muammolar4 soat: xotira oqishi, ulanishlar
BreakpointSinmaguncha oshadiKerakchaSig'im chegarasini topishYangi serverlarga ko'chishdan oldin

Qo'shimcha atamalar: capacity test (breakpoint'ga yaqin), scalability test (resurs qo'shilganda throughput qanchalik o'sadi), volume test (katta hajmdagi ma'lumot bilan, masalan 10 mln mahsulot).

⚠️ Diqqat: "Smoke" so'zi ikki ma'noda ishlatiladi. QA 4 dagi funksional smoke — "eng muhim funksiyalar ishlayaptimi?". Performance'dagi smoke — "skript va tizim minimal yuklamada to'g'ri ishlayaptimi?". Hisobotda qaysi biri ekanini aniq yozing.

k6 hujjati ikki muhim tavsiya beradi:

  1. Doim smoke'dan boshlang, keyin average-load, so'ng boshqa turlar.
  2. Oddiy shakllar ishlating: ramp-up → plato → ramp-down. Yuklamani ko'p marta ko'tarib-tushiradigan "rollercoaster" profillar natijani talqin qilishni qiyinlashtiradi.

🎯 Intervyuda: Soak test nimani topadi? — Qisqa testda ko'rinmaydigan, vaqt o'tishi bilan to'planadigan muammolarni: xotira oqishi (memory leak), yopilmagan DB ulanishlari, disk/log to'lib qolishi, sekin degradatsiya.


5. Jarayon: SLO'dan hisobotgacha {#jarayon}

1. Maqsad va SLO        →  "Nimani isbotlamoqchimiz?"
2. Yuklama modeli       →  qaysi ssenariylar, qancha, qanday nisbatda
3. Muhit va test data   →  prod'ga o'xshash, alohida, tayyorlangan
4. Monitoring           →  server metrikalari test bilan bir vaqtda
5. Bajarish             →  smoke → load → stress/spike/soak, takroriylik
6. Tahlil               →  thresholds, xatolar, percentile, bottleneck
7. Hisobot va qayta test →  topilmalar, tavsiyalar, tuzatishdan keyin qayta o'lchash

1) SLO'ni o'lchanadigan qilib yozing

Yomon talab: "Sayt tez ishlashi kerak". Yaxshi talab:

Endpoint / ssenariyYuklamap95Xato ulushi
GET /api/v1/products300 RPS< 500 ms< 1%
POST /api/v1/orders20 RPS< 1000 ms< 0.5%
Login (OTP tekshirish)30 RPS< 800 ms< 1%

2) Yuklama modeli (workload model)

Analitikadan oling: cho'qqi soatdagi trafik, ssenariylar nisbati, think time. DemoBozor misoli: 60% katalog va mahsulot sahifasi, 25% qidiruv, 10% savatcha, 5% buyurtma berish.

3) Muhit va ma'lumotlar

  • Muhit prod'ga imkon qadar o'xshash bo'lsin: server o'lchamlari, baza hajmi, kesh sozlamalari.
  • Har VU har xil foydalanuvchi va har xil mahsulotlar bilan ishlasin — aks holda hamma narsa keshdan qaytadi va natija "juda yaxshi" chiqadi.
  • To'lov provayderi, SMS shlyuz kabi tashqi xizmatlarni stub/mock bilan almashtiring. Ularga yuklama berish — boshqa kompaniya tizimiga yuklama berish degani.

4) Monitoring

k6 faqat "mijoz tomondan" ko'radi. Sababni topish uchun test vaqtida server CPU/xotira, DB sekin so'rovlari, ulanishlar soni, navbatlar, GC pauzalarini ham kuzating.

Ko'p uchraydigan xatolar

XatoOqibati
Yuklamani noutbukdan, Wi-Fi orqali berishServer emas, sizning noutbuk/tarmoq "bo'g'iz" bo'lib qoladi
sleep() yo'qReal foydalanuvchiga o'xshamagan, haddan tashqari agressiv yuklama
Hamma VU bitta mahsulotni so'raydiKesh hammasini qaytaradi, baza sinovdan o'tmaydi
Faqat latency'ga qarashTez qaytgan 500 xatolar e'tibordan chetda qoladi
Server monitoringisiz test"Sekin" ekanini bilasiz, lekin nega ekanini emas
Bir marta ishlatib xulosa qilishShovqin (noise) natijani buzadi — 2–3 marta takrorlang

6. k6 bilan tanishuv: o'rnatish va birinchi skript {#k6-kirish}

Grafana k6 — ochiq kodli load testing vositasi. Skriptlar JavaScript (yoki TypeScript) da yoziladi, lekin k6 Node.js emas: u Go'da yozilgan va o'zining JS runtime'idan foydalanadi — shuning uchun ko'p npm paketlari ishlamaydi. Kuchli tomonlari: CLI-first, kodda yozilgan thresholds (CI uchun qulay), kam resurs bilan ko'p VU.

Versiyalar (2026-yil oktabr): v2.0.0 (2026-yil 11-may) eskirgan API va buyruqlarni olib tashladi, eng so'nggi reliz — v2.3.0 (2026-yil 21-sentabr). v2 dagi o'quvchiga ta'sir qiladigan o'zgarishlar:

v1 dav2 da
k6 login cloudk6 cloud login
k6 cloud script.jsk6 cloud run script.js
--no-summary--summary-mode=disabled
externally-controlled executorolib tashlangan
options.ext.loadimpactoptions.cloud

TypeScript fayllar k6 v0.57 dan beri qo'shimcha sozlamasiz ishga tushadi.

O'rnatish

# macOS (Homebrew)
brew install k6

# Windows
winget install k6 --source winget

# Docker
docker pull grafana/k6

# tekshirish
k6 version

Linux (Debian/Ubuntu, Fedora) uchun buyruqlarni rasmiy o'rnatish sahifasidan oling — u yerda repository kalitini qo'shish qadami bor.

Nishon: QuickPizza

QuickPizza — Grafana'ning o'quv ilovasi. Ikki variant:

# 1) Lokal (tavsiya etiladi — xohlagancha yuklama bera olasiz)
docker run --rm -it -p 3333:3333 ghcr.io/grafana/quickpizza-local:latest
# brauzerda: http://localhost:3333

# 2) Ommaviy demo: https://quickpizza.grafana.com
#    faqat KICHIK testlar uchun (bir necha VU, qisqa vaqt)

Birinchi skript: smoke test

import http from "k6/http";
import { check, sleep } from "k6";

// BASE_URL berilmasa — lokal QuickPizza (Docker)
const BASE_URL = __ENV.BASE_URL || "http://localhost:3333";

export const options = {
  vus: 2, // 2 ta virtual foydalanuvchi
  duration: "20s", // 20 soniya davomida
};

export default function () {
  const res = http.get(`${BASE_URL}/`);
  check(res, {
    "status 200": (r) => r.status === 200,
  });
  sleep(1); // "o'ylash vaqti" (think time)
}
k6 run smoke.js                                              # lokal QuickPizza
k6 run -e BASE_URL=https://quickpizza.grafana.com smoke.js   # ommaviy demo (kichik!)
k6 new my-test.js                                            # tayyor shablon yaratish

k6 skriptining hayot sikli

QismNecha marta ishlaydiNima uchun
init (fayl tepasi: import, options, open())Har VU uchun bir martaSozlama, fayllarni o'qish
setup()Butun testda bir martaMuhitni tekshirish, token olish; qaytgan qiymat default ga uzatiladi
default (yoki exec funksiya)Har VU qayta-qayta (iteratsiya)Foydalanuvchi ssenariysi
teardown()Butun testda bir martaTozalash, xabar yuborish

🧠 Esda tuting: VU — virtual foydalanuvchi (bitta "parallel ishchi"). Iteratsiya — default funksiyasining bir marta to'liq bajarilishi. 2 VU × 20 s, har iteratsiyada sleep(1) → ko'pi bilan 2 × 20 = 40 iteratsiya; amalda biroz kamroq, chunki har iteratsiyaga so'rov vaqti ham qo'shiladi.


7. k6 chuqurroq: checks, thresholds, scenarios, metrikalar, data {#k6-chuqur}

Load test: stages + thresholds + tags + custom metrikalar

import http from "k6/http";
import { check, group, sleep } from "k6";
import { Trend, Rate } from "k6/metrics";

const BASE_URL = __ENV.BASE_URL || "http://localhost:3333";

// o'zimizning (custom) metrikalar
const pizzaCalories = new Trend("pizza_calories");
const vegetarianOk = new Rate("vegetarian_ok");

export const options = {
  stages: [
    { duration: "30s", target: 10 }, // ramp-up: 0 → 10 VU
    { duration: "1m", target: 10 }, // plato: 10 VU
    { duration: "30s", target: 0 }, // ramp-down
  ],
  thresholds: {
    http_req_failed: ["rate<0.01"], // xatolar < 1%
    http_req_duration: ["p(95)<500", "p(99)<1000"], // umumiy SLO
    "http_req_duration{name:PizzaAPI}": ["p(95)<800"], // faqat pizza API uchun
    checks: ["rate>0.99"],
    vegetarian_ok: ["rate==1"],
  },
};

export default function () {
  group("bosh sahifa", () => {
    const res = http.get(`${BASE_URL}/`, { tags: { name: "HomePage" } });
    check(res, { "bosh sahifa 200": (r) => r.status === 200 });
  });

  group("pizza tavsiyasi", () => {
    const payload = JSON.stringify({
      maxCaloriesPerSlice: 500,
      mustBeVegetarian: true,
      excludedIngredients: [],
      excludedTools: [],
      maxNumberOfToppings: 6,
      minNumberOfToppings: 2,
    });
    const res = http.post(`${BASE_URL}/api/pizza`, payload, {
      headers: {
        "Content-Type": "application/json",
        Authorization: "token abcdef0123456789", // QuickPizza demo token
      },
      tags: { name: "PizzaAPI" },
    });

    const ok = check(res, {
      "pizza 200": (r) => r.status === 200,
      "pizza nomi bor": (r) => r.json("pizza.name") !== undefined,
    });
    if (ok) {
      pizzaCalories.add(res.json("calories"));
      vegetarianOk.add(res.json("vegetarian") === true);
    }
  });

  sleep(1);
}

Muhim tushunchalar:

  • **check — tekshiruv, lekin o'zi testni yiqitmaydi**. Natija checks metrikasiga yoziladi. Testni yiqitish uchun checks: ['rate>0.99'] kabi threshold qo'ying.
  • **thresholds — SLO'ning kodga aylangan ko'rinishi. Biror threshold buzilsa, k6 nol bo'lmagan exit code** bilan tugaydi → CI pipeline qizil bo'ladi.
  • **tags: { name: 'PizzaAPI' }** — so'rovlarni guruhlash. 'http_req_duration{name:PizzaAPI}' bilan faqat shu endpoint'ga alohida SLO qo'yasiz.
  • **group()** — natijalarni mantiqiy bloklarga ajratadi (full summary rejimida guruh bo'yicha ko'rinadi).
  • **res.json('pizza.name')** — JSON ichidan GJSON yo'li bilan qiymat olish.
  • Custom metrikalar: Counter (yig'indi), Gauge (oxirgi qiymat), Rate (ulush), Trend (taqsimot: avg, p95...).

💡 Maslahat: Threshold buzilganda testni darhol to'xtatish uchun: http_req_failed: [{ threshold: 'rate<0.05', abortOnFail: true, delayAbortEval: '30s' }]. delayAbortEval — boshida yetarli namuna yig'ilishini kutish.

Scenarios va executor'lar

Bitta testda bir nechta ssenariyni turli yuklama shakllari bilan aralashtirish mumkin. k6 v2 dagi executor'lar:

ExecutorModelNima qiladi
shared-iterationsyopiqBelgilangan jami iteratsiyalarni VU'lar bo'lishib bajaradi
per-vu-iterationsyopiqHar VU aniq N marta bajaradi
constant-vusyopiqDoimiy VU soni, belgilangan vaqt
ramping-vusyopiqVU soni bosqichma-bosqich o'zgaradi (stages)
constant-arrival-rateochiqSekundiga doimiy iteratsiya boshlanadi
ramping-arrival-rateochiqIteratsiya tezligi bosqichma-bosqich o'zgaradi
import http from "k6/http";
import { check, sleep } from "k6";

const BASE_URL = __ENV.BASE_URL || "http://localhost:3333";
const HEADERS = {
  "Content-Type": "application/json",
  Authorization: "token abcdef0123456789",
};

export const options = {
  scenarios: {
    // ochiq model: sekundiga 10 ta yangi "tashrif", javob sekinlashsa ham
    browse: {
      executor: "constant-arrival-rate",
      exec: "browse",
      rate: 10,
      timeUnit: "1s",
      duration: "2m",
      preAllocatedVUs: 20,
      maxVUs: 50,
    },
    // yopiq model: 5 VU, 30 soniyadan keyin boshlanadi
    order: {
      executor: "ramping-vus",
      exec: "order",
      startTime: "30s",
      stages: [
        { duration: "30s", target: 5 },
        { duration: "1m", target: 5 },
      ],
    },
  },
  thresholds: {
    "http_req_duration{scenario:browse}": ["p(95)<400"],
    "http_req_duration{scenario:order}": ["p(95)<900"],
    http_req_failed: ["rate<0.01"],
  },
};

export function browse() {
  const res = http.get(`${BASE_URL}/`);
  check(res, { "browse 200": (r) => r.status === 200 });
}

export function order() {
  const res = http.post(
    `${BASE_URL}/api/pizza`,
    JSON.stringify({
      mustBeVegetarian: true,
      maxNumberOfToppings: 5,
      minNumberOfToppings: 2,
    }),
    { headers: HEADERS },
  );
  check(res, { "order 200": (r) => r.status === 200 });
  sleep(2);
}

Scenario parametrlari: executor (majburiy), exec (qaysi funksiya), startTime, gracefulStop, env, tags, options (masalan, brauzer sozlamalari).

Spike test: aksiya push'i

import http from "k6/http";
import { check } from "k6";

const BASE_URL = __ENV.BASE_URL || "http://localhost:3333";

export const options = {
  scenarios: {
    aksiya_spike: {
      executor: "ramping-arrival-rate",
      startRate: 5, // soniyasiga 5 iteratsiya
      timeUnit: "1s",
      preAllocatedVUs: 50,
      maxVUs: 300,
      stages: [
        { target: 5, duration: "1m" }, // odatiy fon trafik
        { target: 100, duration: "10s" }, // push yuborildi — keskin sakrash
        { target: 100, duration: "1m" }, // cho'qqi
        { target: 5, duration: "10s" }, // pasayish
        { target: 5, duration: "2m" }, // tizim tiklandimi?
      ],
    },
  },
  thresholds: {
    http_req_failed: [
      { threshold: "rate<0.05", abortOnFail: true, delayAbortEval: "30s" },
    ],
    http_req_duration: ["p(95)<1500"],
  },
};

export default function () {
  const res = http.get(`${BASE_URL}/`);
  check(res, { "status 200": (r) => r.status === 200 });
}

⚠️ Diqqat: Bu skript soniyasiga 100 iteratsiyagacha yuklama beradi — uni faqat lokal QuickPizza yoki o'z test muhitingizga qarshi ishlating. Ommaviy demo saytlar kichik testlar uchun mo'ljallangan.

Oxiridagi 2 daqiqalik "tinch" bosqich muhim: spike'dan keyin tizim o'zi tiklanadimi (latency normal holatga qaytadimi, xatolar to'xtaydimi) — buni ham tekshiramiz.

Soak va breakpoint profillari

// Soak: 4 soat o'rtacha yuklama
export const soakOptions = {
  stages: [
    { duration: "5m", target: 50 },
    { duration: "4h", target: 50 },
    { duration: "5m", target: 0 },
  ],
};

// Breakpoint: sinmaguncha oshiramiz, xatolar 5% dan oshsa — to'xtatamiz
export const breakpointOptions = {
  scenarios: {
    breakpoint: {
      executor: "ramping-arrival-rate",
      preAllocatedVUs: 100,
      maxVUs: 2000,
      stages: [{ duration: "30m", target: 2000 }],
    },
  },
  thresholds: {
    http_req_failed: [{ threshold: "rate<0.05", abortOnFail: true }],
    http_req_duration: [{ threshold: "p(95)<2000", abortOnFail: true }],
  },
};

(Real skriptda bularning birini export const options = ... sifatida ishlatasiz.)

Test data: SharedArray va setup()

import http from "k6/http";
import { check, sleep } from "k6";
import { SharedArray } from "k6/data";
import exec from "k6/execution";

const BASE_URL = __ENV.BASE_URL || "http://localhost:3333";

// open() faqat init qismida ishlaydi; SharedArray xotirani VU'lar orasida bo'lishadi
const tokens = new SharedArray("tokens", function () {
  return JSON.parse(open("./data/tokens.json")).tokens;
});

export const options = { vus: 5, duration: "30s" };

export function setup() {
  const res = http.get(BASE_URL);
  if (res.status !== 200) {
    throw new Error(`Muhit tayyor emas: status ${res.status}`);
  }
  return { startedAt: new Date().toISOString() }; // default() ga uzatiladi
}

export default function (data) {
  // har bir VU test oxirigacha bitta "foydalanuvchi" bo'lib qoladi
  const token = tokens[(exec.vu.idInTest - 1) % tokens.length];
  const res = http.post(
    `${BASE_URL}/api/pizza`,
    JSON.stringify({ mustBeVegetarian: true }),
    {
      headers: {
        "Content-Type": "application/json",
        Authorization: `token ${token}`,
      },
    },
  );
  check(res, { "pizza 200": (r) => r.status === 200 });
  sleep(1);
}

export function teardown(data) {
  console.log(`Test ${data.startedAt} da boshlangan edi`);
}

data/tokens.json:

{
  "tokens": ["loadtestuser0004", "loadtestuser0005", "loadtestuser0006"]
}

🧠 Esda tuting: open() faqat init qismida ishlaydi (default ichida emas). Katta fayllarni SharedArray bilan o'qing — aks holda har VU faylning o'z nusxasini xotirada saqlaydi.

k6 browser: frontend metrikalari bilan

k6 da k6/browser moduli bor — haqiqiy Chromium brauzerida sahifani ochib, Web Vitals (LCP, CLS, INP, FCP, TTFB) ni o'lchaydi. Kompyuterda Chromium asosidagi brauzer (masalan, Google Chrome) bo'lishi kerak.

import { browser } from "k6/browser";
import { check } from "k6";

const BASE_URL = __ENV.BASE_URL || "http://localhost:3333";

export const options = {
  scenarios: {
    ui: {
      executor: "shared-iterations",
      vus: 1,
      iterations: 3,
      options: { browser: { type: "chromium" } },
    },
  },
  thresholds: {
    browser_web_vital_lcp: ["p(75)<2500"],
    browser_web_vital_cls: ["p(75)<0.1"],
  },
};

export default async function () {
  const page = await browser.newPage();
  try {
    await page.goto(BASE_URL);
    await page.locator('button[name="pizza-please"]').click();
    const title = await page.locator("h1").textContent();
    check(title, { "sarlavha bor": (t) => t !== null && t.length > 0 });
  } finally {
    await page.close();
  }
}

Odatiy amaliyot: ko'p protokol (HTTP) VU + bir nechta brauzer VU — backend yuklama ostida bo'lganda foydalanuvchi sahifani qanday his qilishini ko'rish. k6 da Playwright uslubidagi expect assertion'lari ham bor (k6-testing kutubxonasi), lekin u hozircha preview holatida.


8. Natijani o'qish, hisobot va CI {#natija}

End-of-test summary

k6 v2 da summary standart holatda compact rejimda chiqadi (--summary-mode=full — guruh va ssenariylar bo'yicha batafsil). Quyida rasmiy k6 hujjatidagi compact namunadan qisqartirilgan parcha:

  █ THRESHOLDS

    http_req_duration
    ✓ 'p(95)<1500' p(95)=148.21ms
    ✓ 'p(90)<2000' p(90)=146.88ms

    http_req_failed
    ✓ 'rate<0.01' rate=0.00%


  █ TOTAL RESULTS

    checks_total.......................: 90      13.122179/s
    checks_succeeded...................: 100.00% 90 out of 90
    checks_failed......................: 0.00%   0 out of 90

    HTTP
    http_req_duration..................: avg=140.36ms   min=119.08ms med=140.96ms max=154.63ms p(90)=146.88ms p(95)=148.21ms
      { expected_response:true }.......: avg=140.36ms   min=119.08ms med=140.96ms max=154.63ms p(90)=146.88ms p(95)=148.21ms
    http_req_failed....................: 0.00%  0 out of 45
    http_reqs..........................: 45     6.56109/s

    EXECUTION
    iteration_duration.................: avg=152.38ms   min=119.37ms med=141.27ms max=684.62ms p(90)=147.11ms p(95)=148.39ms
    iterations.........................: 45     6.56109/s
    vus................................: 1      min=1       max=1

Qanday o'qiladi:

  1. THRESHOLDS — eng birinchi qaraladigan joy. ✓ — SLO bajarildi, ✗ — buzildi.
  2. checks — funksional to'g'rilik: yuklama ostida javoblar hali ham to'g'rimi?
  3. http_req_duration — med (p50) va p(95) ni solishtiring. Ular orasidagi katta farq — "dum" (tail latency) muammosi.
  4. **{ expected_response:true }** qatori — faqat muvaffaqiyatli javoblar vaqti. Asosiy qator bilan farq qilsa, xatoli javoblar vaqtni buzayotgan bo'ladi.
  5. http_req_failed va http_reqs — xato ulushi va throughput (sekundiga so'rov).
  6. vus — haqiqatda nechta VU ishlagan (arrival-rate'da maxVUs yetmasa, k6 ogohlantiradi).

Bottleneck'ni qidirish

BelgiEhtimoliy sababNimani tekshirish
Yuklama oshgani sari p95 keskin o'sadi, RPS o'smaydiSig'im tugadi ("tizza" nuqtasi)CPU, DB ulanishlari, thread pool
Ma'lum vaqtdan keyin 503/timeout'larConnection pool yoki navbat to'ldiPool o'lchami, navbat uzunligi
Soak testda latency asta-sekin o'sadiXotira oqishi, yopilmagan resurslarXotira grafigi, GC, ulanishlar soni
Faqat bitta endpoint sekinSekin SQL, N+1 so'rov, indeks yo'qDB slow query log, EXPLAIN (QA 12)
http_req_waiting kichik, receiving kattaJavob juda og'irPayload hajmi, siqish (gzip/br), pagination
Lokal tez, CI'da sekinLoad generator'ning o'zi bo'g'izGenerator CPU/tarmog'i

Natijalarni saqlash va vizualizatsiya

k6 run --out json=results.json load.js         # har bir nuqta JSON faylga
K6_WEB_DASHBOARD=true k6 run load.js           # jonli dashboard: http://127.0.0.1:5665
K6_WEB_DASHBOARD=true K6_WEB_DASHBOARD_EXPORT=report.html k6 run load.js  # HTML hisobot

Real vaqtda metrikalarni Grafana Cloud k6, Prometheus remote write, InfluxDB, OpenTelemetry va boshqa tizimlarga ham uzatish mumkin.

Hisobot shabloni

# Performance test hisoboti — DemoBozor aksiya tayyorgarligi

Maqsad:      Aksiya kuni 300 RPS da katalog SLO'si bajariladimi?
Muhit:       staging-perf (prod bilan bir xil instance turi), DB: 2 mln mahsulot
Versiya:     api v2.14.0, build 1842
Yuklama:     ramping-arrival-rate 0→300 it/s 10 daq, 300 it/s da 30 daq
Natijalar:
  | Metrika                         | SLO       | Natija   | Holat |
  | GET /products p95               | < 500 ms  | 430 ms   | OK    |
  | POST /orders p95                | < 1000 ms | 1840 ms  | FAIL  |
  | Xato ulushi                     | < 1%      | 0.4%     | OK    |
Topilmalar:  POST /orders da DB lock kutish; 250+ it/s da pool 100% band
Tavsiyalar:  orders jadvaliga indeks, pool 20→40, qayta test
Ilovalar:    report.html, Grafana dashboard havolasi, skript commit'i

💡 Maslahat: Hisobotda faqat "yiqildi/o'tdi" emas, qaysi yuklamada buzilish boshlanganini yozing ("230 it/s gacha SLO bajarildi, 250 dan keyin p95 2 baravar o'sdi"). Bu jamoaga sig'imni rejalashtirishga yordam beradi.

CI'da performance smoke

Har PR'da og'ir load test kerak emas, lekin qisqa smoke perf test regressiyani erta ushlaydi. GitHub Actions uchun Grafana'ning rasmiy action'lari bor:

name: perf-smoke
on:
  pull_request:

jobs:
  k6:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: grafana/setup-k6-action@v1
      - uses: grafana/run-k6-action@v1
        with:
          path: ./perf/smoke.js
          flags: -e BASE_URL=${{ vars.STAGING_URL }}

Threshold buzilsa, k6 nol bo'lmagan kod bilan chiqadi va job qizil bo'ladi — bu quality gate vazifasini bajaradi. Og'ir testlarni (stress, soak) esa kechasi (schedule) yoki reliz oldidan alohida ishlating. CI haqida batafsil: QA 21.


9. Boshqa vositalar: JMeter, Gatling, Locust {#boshqa-vositalar}

VositaSkript tiliKuchli tomoniE'tibor bering
k6JavaScript / TypeScriptCLI-first, thresholds-as-code, kam resursNode.js emas — npm paketlari cheklangan
Apache JMeterGUI'da test plan (.jmx, XML)Ko'p protokol, katta plagin ekotizimiYuklamani GUI'dan emas, CLI (non-GUI) rejimda bering
GatlingJava, Scala, Kotlin, JavaScript/TypeScriptKuchli DSL, chiroyli HTML hisobotJVM asosida ishlaydi
LocustPythonPython bilan oson, web UIPython bilmaydigan jamoaga mos emas

JMeter'da yuklama testi va HTML hisobotni CLI'dan ishga tushirish (rasmiy hujjatdagi format):

jmeter -n -t test-plan.jmx -l results.jtl -e -o report/

Locust'dagi eng oddiy fayl (locustfile.py, rasmiy quickstart'dagi misolga o'xshash):

from locust import HttpUser, task

class KatalogUser(HttpUser):
    @task
    def katalog(self):
        self.client.get("/")

locust buyrug'idan keyin web UI http://localhost:8089 da ochiladi.

💡 Maslahat: Vositani jamoa tiliga qarab tanlang: frontend/JS jamoa — k6, Java jamoa — Gatling yoki JMeter, Python jamoa — Locust. Tushunchalar (SLO, percentile, ochiq/yopiq model) hammasida bir xil.


10. Frontend va mobil performance {#frontend-mobil}

Backend 200 ms da javob bersa ham, foydalanuvchi sahifani 5 soniyada ko'rishi mumkin: og'ir rasmlar, bloklovchi JavaScript, kech yuklanadigan shriftlar.

Core Web Vitals (web.dev)

MetrikaNimani o'lchaydi"Yaxshi" chegara
LCP (Largest Contentful Paint)Asosiy kontent ko'rinish tezligi≤ 2.5 s
INP (Interaction to Next Paint)Bosish/yozishga javob tezligi≤ 200 ms
CLS (Cumulative Layout Shift)Sahifa elementlarining "sakrashi"≤ 0.1

Chegaralar sahifa yuklanishlarining 75-percentile'ida, mobil va desktop uchun alohida baholanadi. INP 2024-yilda FID o'rniga Core Web Vital bo'ldi.

QA uchun amaliy tekshiruvlar (DemoBozor mahsulot sahifasi):

  • Chrome DevTools → Lighthouse — lab o'lchovi; Performance paneli — nima sekin ekanini ko'rish (QA 9);
  • Network throttling (masalan, "Slow 4G") bilan sahifani ochib ko'ring;
  • narx yoki banner kech yuklanib, tugmalarni pastga "itarib yuborsa" — bu CLS bug'i;
  • rasm o'lchamlari, lazy loading, keshlash header'lari.

🧠 Esda tuting: Lab data (Lighthouse) — bitta qurilmada, boshqariladigan sharoitda. Field data (real foydalanuvchilar, RUM) — haqiqiy qurilma va tarmoqlar. Ikkalasi ham kerak.

Mobil ilovalar

NimaQanday tekshiriladi
Cold/warm start vaqtiIlovani to'liq yopib ochish; Xcode Instruments, Android Studio Profiler
Xotira va oqishlarInstruments (Allocations, Leaks), Android Profiler; uzoq ishlatish ssenariysi
Kadrlar tushishi (jank)Uzun ro'yxatlarni scroll qilish, animatsiyalar
Batareya va tarmoqFon rejimidagi so'rovlar, keraksiz polling
Sekin tarmoqiOS Network Link Conditioner, Proxyman Network Conditions

Mobil testlash bo'yicha to'liq checklist — QA 14.


11. Etika va xavfsizlik qoidalari {#etika}

Load test — bu ataylab katta trafik yaratish. Noto'g'ri nishonga qaratilsa, u DoS hujumidan farq qilmaydi.

  1. Faqat o'zingizga tegishli yoki yozma ruxsat olingan tizimlarni testlang. Boshqa kompaniya saytini "qiziqish uchun" yuklama bilan tekshirish — qonunbuzarlik bo'lishi mumkin.
  2. Umumiy (shared) muhitda test qilishdan oldin DevOps va navbatchi jamoani ogohlantiring, vaqtni kelishing.
  3. Tashqi xizmatlarni (to'lov, SMS, xaritalar) stub qiling — ularning limitlari va narxlari bor.
  4. Har doim to'xtatish mezoni bo'lsin: abortOnFail, maksimal VU, maksimal davomiylik.
  5. Prod'da test faqat alohida kelishuv, monitoring va reja bilan (masalan, past trafikli soatda).
  6. Real foydalanuvchi ma'lumotlarini emas, test data'dan foydalaning.
  7. Ommaviy demo nishonlar (masalan, quickpizza.grafana.com) — faqat kichik o'quv testlari uchun; katta yuklama uchun lokal nusxani ishga tushiring.

12. Amaliy mashqlar {#mashqlar}

Mashq 1: O'rtacha vs mediana

Qidiruv endpoint'ining 10 ta javob vaqti (ms): 200, 210, 190, 205, 2400, 198, 202, 215, 207, 193. O'rtacha va medianani hisoblang. Qaysi biri foydalanuvchi tajribasini yaxshiroq ifodalaydi va SLO'ni qanday yozgan bo'lardingiz?

<details> <summary>💡 Javobni ko'rish</summary>

  • Yig'indi: 200+210+190+205+2400+198+202+215+207+193 = 4220 → o'rtacha 422 ms.
  • Saralangan: 190, 193, 198, 200, 202, 205, 207, 210, 215, 2400 → mediana = (202 + 205) / 2 = 203.5 ms.

Mediana "odatiy" foydalanuvchini ko'rsatadi; o'rtacha bitta 2.4 s lik so'rov tufayli ikki baravar oshib ketgan. SLO percentile bilan yoziladi: masalan, "GET /search uchun p95 < 500 ms va xato ulushi < 1%" — shunda sekin "dum" ham nazoratda bo'ladi.

</details>

Mashq 2: Qaysi test turi?

Har bir vaziyat uchun test turini tanlang:

  1. Yangi k6 skript yozildi, uni birinchi marta ishga tushiryapsiz.
  2. Server 6 soat ishlagandan keyin sekinlashib qolayotganidan shikoyat bor.
  3. "Hayit aksiyasi" push xabari 2 mln foydalanuvchiga bir vaqtda yuboriladi.
  4. Yangi DB serverga ko'chishdan oldin "maksimum nechta buyurtma/s ko'taramiz?" degan savol.
  5. Har haftalik reliz: oddiy kunlik trafikda SLO buzilmadimi?

<details> <summary>💡 Javobni ko'rish</summary>

  1. Smoke — skript va muhit ishlashini minimal yuklamada tekshirish.
  2. Soak — uzoq vaqtli o'rtacha yuklama: xotira oqishi, yopilmagan ulanishlar.
  3. Spike — qisqa vaqtda keskin sakrash va undan keyingi tiklanish.
  4. Breakpoint (capacity) — sinmaguncha oshirib, chegarani topish.
  5. Average-load — odatiy yuklamada regressiya bormi.

</details>

Mashq 3: Little's Law bilan VU hisoblash

Prognoz: aksiya soatida daqiqasiga 120 ta buyurtma ssenariysi. Bitta ssenariy: so'rovlar jami ~2 s + foydalanuvchining o'ylash vaqti 28 s. Nechta VU kerak? Agar sleep() ni olib tashlasangiz, shu throughput uchun nechta VU yetadi va bu nimani anglatadi?

<details> <summary>💡 Javobni ko'rish</summary>

  • λ = 120 / 60 = 2 iteratsiya/s; W = 2 + 28 = 30 s → L = 2 × 30 = 60 VU.
  • sleep() siz: W ≈ 2 s → L = 2 × 2 = 4 VU xuddi shu 2 it/s ni beradi.

Xulosa: think time'siz test real concurrency'ni (bir vaqtdagi sessiyalar, ochiq ulanishlar, xotiradagi sessiyalar) ancha kam ko'rsatadi. Real hayotga yaqin model uchun think time'ni analitikadan oling.

</details>

Mashq 4: Thresholds yozing

SLO: (a) barcha so'rovlarda xato < 0.5%; (b) name:Checkout tegli so'rovlar uchun p95 < 800 ms va p99 < 1500 ms; (c) check'larning 99% dan ko'prog'i o'tsin; (d) xato ulushi 10% dan oshsa, 20 soniyalik "isinish"dan keyin test darhol to'xtasin. options.thresholds ni yozing.

<details> <summary>💡 Javobni ko'rish</summary>

export const options = {
  thresholds: {
    http_req_failed: [
      "rate<0.005",
      { threshold: "rate<0.10", abortOnFail: true, delayAbortEval: "20s" },
    ],
    "http_req_duration{name:Checkout}": ["p(95)<800", "p(99)<1500"],
    checks: ["rate>0.99"],
  },
};

Bitta metrikaga bir nechta threshold berish mumkin: oddiy satr ko'rinishi ham, abortOnFail li obyekt ham bir massivda turishi mumkin. So'rovlarga tags: { name: 'Checkout' } qo'yishni unutmang.

</details>

Mashq 5: Summary'ni talqin qiling

Quyidagi — o'quv misoli (raqamlar xayoliy). Nima bo'lgan va keyingi qadamingiz qanday?

  █ THRESHOLDS

    http_req_duration
    ✗ 'p(95)<500' p(95)=912.40ms

    http_req_failed
    ✗ 'rate<0.01' rate=3.20%

  █ TOTAL RESULTS

    HTTP
    http_req_duration..................: avg=310.11ms min=95.20ms med=180.33ms max=30.01s p(90)=640.12ms p(95)=912.40ms
      { expected_response:true }.......: avg=205.47ms min=95.20ms med=176.90ms max=1.20s  p(90)=420.55ms p(95)=488.02ms
    http_req_failed....................: 3.20%  154 out of 4800
    http_reqs..........................: 4800   39.6/s

<details> <summary>💡 Javobni ko'rish</summary>

  • Ikkala threshold buzilgan → test FAIL, CI qizil.
  • Muvaffaqiyatli javoblar (expected_response:true) p95 = 488 ms — ya'ni SLO'ga deyarli mos. Umumiy p95 ni xatoli javoblar buzmoqda.
  • max=30.01s — timeout'ga o'xshaydi: 3.2% (154 ta) so'rov uzoq kutib, xato bilan tugagan.
  • Keyingi qadamlar: xatolar qaysi endpoint va qaysi status kodida ekanini aniqlash (tag'lar, --out json), server loglari va monitoringda shu vaqtdagi CPU/DB pool/timeout'larni ko'rish, kichikroq yuklamada qayta ishga tushirib, buzilish qaysi nuqtada boshlanishini topish.

</details>

Mashq 6: Spike ssenariysini yozing

Talab: 2 daqiqa davomida soniyasiga 10 iteratsiya (fon), keyin 15 soniyada 150 it/s gacha sakrash, 1 daqiqa ushlab turish, 15 soniyada 10 ga qaytish va yana 3 daqiqa kuzatish. Executor va stages ni yozing.

<details> <summary>💡 Javobni ko'rish</summary>

export const options = {
  scenarios: {
    spike: {
      executor: "ramping-arrival-rate",
      startRate: 10,
      timeUnit: "1s",
      preAllocatedVUs: 100,
      maxVUs: 500,
      stages: [
        { target: 10, duration: "2m" },
        { target: 150, duration: "15s" },
        { target: 150, duration: "1m" },
        { target: 10, duration: "15s" },
        { target: 10, duration: "3m" },
      ],
    },
  },
};

Ochiq model (ramping-arrival-rate) tanlandi: server sekinlashsa ham yangi foydalanuvchilar kelishda davom etadi — haqiqiy push'dagi kabi. maxVUs yetmasa, k6 ogohlantirish beradi — demak generator'ga ko'proq VU kerak.

</details>

Mashq 7: Performance bug report

Stress testda POST /api/v1/orders 250 it/s dan keyin p95 3.1 s ga chiqdi va 4% 503 qaytdi. Bug report'da qaysi ma'lumotlar bo'lishi kerak? (QA 8 formatini eslang.)

<details> <summary>💡 Javobni ko'rish</summary>

  • Sarlavha: "POST /api/v1/orders: 250 it/s dan yuqori yuklamada p95 3.1 s va 4% 503 (SLO: p95 < 1 s, xato < 0.5%)".
  • Muhit: staging-perf, API versiyasi/build, DB hajmi, instance turlari.
  • Qayta hosil qilish: skript fayli (commit havolasi), aniq options (executor, stages), ishga tushirish buyrug'i.
  • Kutilgan/haqiqiy natija: SLO jadvali bilan solishtirish.
  • Dalillar: k6 summary, HTML hisobot, Grafana dashboard skrinshotlari (CPU, DB pool, xatolar) — vaqt oralig'i bilan.
  • Kuzatuv: buzilish qaysi yuklamadan boshlangani, 503 lar qaysi komponentdan kelgani (gateway yoki servis).
  • Jiddiylik/ustuvorlik: aksiya sanasiga bog'liq holda (aksiyagacha muddat qisqa bo'lsa — yuqori).

</details>


13. O'zingizni tekshiring {#checklist}

  • [ ] Nega SLO o'rtacha emas, percentile bilan yozilishini tushuntira olaman
  • [ ] Little's Law bilan kerakli VU sonini hisoblay olaman
  • [ ] 6 ta test turini va ularning maqsadini ayta olaman
  • [ ] Ochiq va yopiq yuklama modelining farqini bilaman
  • [ ] k6'da stages, thresholds, scenarios, tags va custom metrika yoza olaman
  • [ ] Summary'ni o'qib, keyingi qadamni belgilay olaman
  • [ ] Core Web Vitals chegaralarini bilaman
  • [ ] Load test etikasi qoidalariga amal qilaman

Xulosa {#xulosa}

  • Performance testing — tezlik, barqarorlik va sig'imni o'lchash; funksional testlar topmaydigan muammolarni topadi.
  • SLO'larni percentile (p95/p99) va xato ulushi bilan yozing; o'rtacha qiymat aldaydi.
  • Little's Law (L = λ × W) VU sonini hisoblashga, Apdex natijani biznes tiliga o'girishga yordam beradi.
  • Har doim smokedan boshlang; keyin average-load, stress, spike, soak, breakpoint — maqsadga qarab.
  • k6 v2: thresholds SLO'ni kodga aylantiradi va CI'da quality gate bo'ladi; ochiq model uchun arrival-rate executor'larini ishlating.
  • k6 faqat mijoz tomonini ko'radi — sababni topish uchun server monitoringi shart.
  • Foydalanuvchi tezligi faqat backend emas: Core Web Vitals (LCP ≤ 2.5 s, INP ≤ 200 ms, CLS ≤ 0.1) va mobil start/xotira ham muhim.
  • Keyingi dars: QA 24: Security testing asoslari — OWASP Top 10:2025, IDOR, injection va QA xavfsizlik checklisti

Manbalar {#manbalar}

  1. Grafana k6 — rasmiy hujjatlar
  2. grafana/k6 — GitHub releases
  3. k6 v2.0.0 reliz eslatmalari (breaking changes)
  4. k6 — Install k6
  5. k6 — Load test types
  6. k6 — Thresholds
  7. k6 — Executors
  8. k6 — Built-in metrics
  9. k6 — End of test summary
  10. k6 — Web dashboard
  11. k6 — Using k6 browser
  12. grafana/quickpizza — GitHub
  13. grafana/run-k6-action — GitHub
  14. web.dev — Web Vitals
  15. Wikipedia — Apdex
  16. Wikipedia — Little's law
  17. Apache JMeter — Generating Report Dashboard
  18. Gatling — JavaScript/TypeScript installation guide
  19. Locust — Quickstart

Markdown manba

iOS Lessons