IlmHamroh
JavaScript Full-stack/24-qism. Node.js47/55-dars16 daqiqa
Mundarija (24)

Node.js CPU profiling: --cpu-prof, flamegraph va hot path'ni topish

Qisqacha: Sekin kodni taxmin bilan emas, o'lchov bilan topasiz. node --cpu-prof app.js dastur tugaganda .cpuprofile faylini yozadi: har ~1 ms da "hozir qaysi funksiya ishlayapti" namunasi. Undan ikki raqam olinadi: self (funksiyaning o'zida o'tgan vaqt) va total (u chaqirganlar bilan). Flamegraph — shu ma'lumotning rasmi: kenglik — vaqt, balandlik — chaqiruvlar chuqurligi. Kanonda valyuta tahlil (1 mln qator) profili vaqtning 22 % i runMicrotasks ga — for await ning har qatordagi Promise'iga ketishini ko'rsatdi. Biz 'line' hodisasi bilan o'lchadik: 645 → 567 ms.

Bu darsda

  • --cpu-prof bilan profil yig'ib, .cpuprofile ichini o'zingiz tahlil qilasiz.
  • Self va total vaqt farqini, "hot path" (issiq yo'l) nimaligini tushuntira olasiz.
  • Flamegraph va flame chart'ni o'qiysiz.
  • Inlining profilni qanday "aldashini" va qator darajasidagi ma'lumot bilan uni qanday ochishni bilasiz.
  • --prof / --prof-process va 0x ni qachon ishlatishni bilasiz.

Oldin bilishingiz kerak: Event loop'ni bloklash, Performansni o'lchash va benchmarking, DevTools: Performance paneli, Node'ni debug qilish.

1. Nega bu kerak?

valyuta tahlil katta.csv 1 million qatorni 0.8 soniyada qayta ishlaydi. Tezroq bo'lishi mumkinmi? Qayerni tuzatish kerak? Ko'pchilik "aniq CSV ajratish sekin" deb taxmin qiladi va o'sha joyni qayta yozadi. Keyin o'lchaydi — farq yo'q.

Event loop'ni bloklash darsida qancha vaqt ketishini o'lchadingiz. Profil esa qayerga ketishini ko'rsatadi. Brauzerda DevTools Performance paneli shuni qiladi. Node'da xuddi shu V8 profiler bor.

O'xshatish: oylik xarajat. "Pul qayerga ketyapti?" degan savolga xotiradan javob bersangiz — "ovqatga". Bank ko'chirmasini ochsangiz — taksi, obunalar, mayda xaridlar. Profil — kodingizning bank ko'chirmasi.

2. --cpu-prof: profil yig'ish

2.1 Tajriba dasturi

Kichik hisobot dasturi: 300 000 qator yasaydi, har valyuta o'rtachasini va nechta turli kurs uchraganini hisoblaydi (sekin.mjs, qisqartirilgan):

js
function parseRow(line) {
  const [date, code, rate] = line.split(",");
  return { date, code, rate: Number(rate) };
}

function contains(list, value) {
  for (const x of list) if (x === value) return true;
  return false;
}

function summarize(rows) {
  const sums = {};
  const seen = []; // turli kurslar
  for (const line of rows) {
    const r = parseRow(line);
    sums[r.code] ??= { n: 0, total: 0 };
    sums[r.code].n++;
    sums[r.code].total += r.rate;
    if (!contains(seen, r.rate)) seen.push(r.rate);
  }
  // … o'rtachalar va natija satri
}

Faylda bu funksiyalar 12–34-qatorlarda (contains ning sikli — 18-qator). Natija:

text
USD 11497.85 | EUR 11497.85 | RUB 11497.86 | IDR 11497.86 | turli kurs: 997

2.2 Profil

bash
node --cpu-prof --cpu-prof-dir=prof sekin.mjs

Dastur odatdagidek ishlaydi, tugaganda prof/ papkasida fayl paydo bo'ladi:

text
CPU.20261023.221159.12880.0.001.cpuprofile

Nom: sana, vaqt, PID va tartib raqami (hujjat bo'yicha CPU.${yyyymmdd}.${hhmmss}.${pid}.${tid}.${seq}.cpuprofile). Bayroqlar:

Bayroq Nima
--cpu-prof Profilni yoqish, chiqishda yozish
--cpu-prof-dir=prof Qaysi papkaga
--cpu-prof-name=… Fayl nomi (${pid} o'rinbosari bilan)
--cpu-prof-interval=100 Namuna oralig'i mikrosekundda (sukut 1000)

Maslahat: Profil yig'ilgan dastur biroz sekinroq ishlaydi va yozish uchun vaqt oladi. Profil ichidagi vaqtlarni oddiy ishga tushirish vaqti bilan aralashtirmang.

2.3 .cpuprofile ichida nima bor

Bu oddiy JSON, uch asosiy maydon bilan:

  • nodes — chaqiruvlar daraxti: har tugun bitta funksiya chaqiruv yo'lida (callFrame: nomi, fayl, qator), children — u chaqirganlar.
  • samples — har ~1 ms da yozilgan tugun ID'lari: "shu lahzada qaysi tugun ishlayotgan edi".
  • timeDeltas — namunalar orasidagi vaqt (mikrosekund).

Self vaqtni o'zingiz hisoblay olasiz. Quyidagi blok — 4 tugunli qo'lda yozilgan mini-profil (toza JS, saytda ham ishlaydi):

js
const fn = (functionName) => ({ functionName });
const profile = {
  nodes: [
    { id: 1, callFrame: fn("(root)"), children: [2] },
    { id: 2, callFrame: fn("summarize"), children: [3, 4] },
    { id: 3, callFrame: fn("parseRow"), children: [] },
    { id: 4, callFrame: fn("contains"), children: [] },
  ],
  samples: [2, 3, 3, 4, 4, 4, 2, 3, 4, 4],
  timeDeltas: new Array(10).fill(1000), // mikrosekund
};

const self = new Map();
profile.samples.forEach((id, i) => {
  self.set(id, (self.get(id) ?? 0) + profile.timeDeltas[i] / 1000);
});
const byId = new Map(profile.nodes.map((n) => [n.id, n]));
const total = (id) =>
  (self.get(id) ?? 0) +
  byId.get(id).children.reduce((sum, c) => sum + total(c), 0);

for (const n of profile.nodes.slice(1)) {
  const name = n.callFrame.functionName;
  const own = self.get(n.id) ?? 0;
  console.log(`${name}: self ${own} ms, total ${total(n.id)} ms`);
}

Konsolda:

text
summarize: self 2 ms, total 10 ms
parseRow: self 3 ms, total 3 ms
contains: self 5 ms, total 5 ms
  • Self — namuna aynan shu tugunda bo'lgan vaqt. contains — 5 ms: eng ko'p.
  • Total — o'zi + bolalarining total'i. summarize ning o'zi atigi 2 ms, lekin total 10 ms — butun ish uning ostida.
  • Hot path (issiq yo'l) — total eng katta bo'lgan zanjir: summarize → contains. Optimallashtirishni shu yerdan boshlaysiz.

3. Haqiqiy profil va inlining tuzog'i

3.1 Funksiyalar bo'yicha

Xuddi shu hisobni haqiqiy .cpuprofile uchun yozdik (tahlil-prof.mjs — yuqoridagi blokning to'liq versiyasi, callFrame.url va lineNumber bilan). sekin.mjs profili — contains qatoriga va self/total ustunlariga qarang:

text
profil: 15 KB, 74 tugun, 252 namuna
jami 416 ms
  self %   self ms  total ms  funksiya
   37.7 %      157       302  summarize sekin.mjs:22
   31.8 %      132       132  parseRow sekin.mjs:12
   10.0 %       42        42  (garbage collector) :0
    9.5 %       40        40  makeRows sekin.mjs:2
    3.1 %       13        13  (program) :0
    3.1 %       13        13  contains sekin.mjs:17
    2.0 %        8       351  (anonim) sekin.mjs:1

Kutilmagan: contains — atigi 3.1 %. Demak muammo unda emasmi? (garbage collector) — xotira tozalash (GC darsi), (program) — Node'ning o'zi, (anonim) sekin.mjs:1 — modulning yuqori darajasi.

3.2 Qatorlar bo'yicha

.cpuprofile da har tugunning positionTicks maydoni bor — qaysi qatorda nechta namuna tushgani. Shu bo'yicha saraladik:

text
  75 namuna (29.8 %)  sekin.mjs:18 (summarize)
  66 namuna (26.2 %)  sekin.mjs:13 (parseRow)
  21 namuna (8.3 %)  sekin.mjs:6 (makeRows)
  15 namuna (6.0 %)  sekin.mjs:14 (parseRow)
  14 namuna (5.6 %)  sekin.mjs:27 (summarize)

Birinchi qatorga qarang: 18-qator — bu contains ning sikli (for (const x of list)). Lekin u summarize nomi bilan yozilgan! Sabab — inlining: V8 ning optimallashtiruvchi kompilyatori (TurboFan) kichik va tez-tez chaqiriladigan contains ni summarize ning ichiga "qo'yib yubordi". Mashina kodida endi alohida contains chaqiruvi yo'q — vaqt summarize ga yoziladi, qator raqami esa haqiqatni aytadi.

Diqqat: Funksiyalar ro'yxatida kichik funksiya "arzon" ko'rinsa, unga ishonmang — qatorlar bo'yicha ham qarang. DevTools va VS Code ham .cpuprofile ni ochganda qator darajasidagi vaqtni manba kod yonida ko'rsatadi (hujjat bo'yicha; biz sinamadik).

Yana bir kuzatuv: dastlabki variantda contains o'rniga seen.includes(…) bor edi. O'shanda vaqt umuman sekin.mjs:31 — console.log(summarize(makeRows(…))) qatoriga yozildi. O'rnatilgan metodlar ham chaqiruvchiga "singib" ketishi mumkin — shuning uchun tajriba uchun alohida contains funksiyasini yozdik.

3.3 Tuzatish va qayta o'lchash

contains har qatorda 997 tagacha elementli massivni ko'rib chiqadi — O(n) (Big-O). Set da tekshirish — O(1):

diff
-  const seen = []; // turli kurslar
+  const seen = new Set(); // turli kurslar
 …
-    if (!contains(seen, r.rate)) seen.push(r.rate);
+    seen.add(r.rate);
 …
-  return `… | turli kurs: ${seen.length}`;
+  return `… | turli kurs: ${seen.size}`;

Natija o'zgarmadi (turli kurs: 997). Profil (tez.mjs):

text
jami 313 ms
  self %   self ms  total ms  funksiya
   47.4 %      148       148  parseRow tez.mjs:12
   14.2 %       44       193  summarize tez.mjs:22
   13.8 %       43        43  (garbage collector) :0
   13.0 %       41        41  makeRows tez.mjs:2

18-qator ro'yxatdan yo'qoldi, endi eng issiq joy — parseRow (split va obyekt yaratish). Oddiy ishga tushirish vaqti (7 marta, mediana, ikki seans):

sekin.mjs va tez.mjs: ishga tushirish vaqti (mediana, 7 marta)
  • sekin (massiv + contains), 1-seans471 ms
  • tez (Set), 1-seans386 ms
  • sekin, 2-seans494 ms
  • tez, 2-seans334 ms

Manba: O'lchandi: Node 24.21.0, Windows 11, i5-12500H, 2026-10-23 (mashina parallel ishlar bilan band edi)

Ikki seans orasida ham raqamlar tebrandi — mashina boshqa ishlar bilan band edi. Shuning uchun har doim oldin va keyin bitta seansda o'lchang. Farq barqaror: ~85–160 ms.

Keyingi qadam — parseRow. Lekin to'xtang: dastur 0.4 soniyada tugaydi va kuniga bir marta ishlaydi. Optimallashtirish — vaqt sarfi. Profil "qayerda" ni aytadi, "arziydimi" ni siz hal qilasiz.

Tekshirib ko'ring: Profilda formatSana funksiyasining self vaqti 2 %, total vaqti 60 %. Uni qayta yozish dasturni tezlashtiradimi?

Javob

Uning o'zini qayta yozish deyarli foyda bermaydi — self atigi 2 %. 60 % uning chaqirgan funksiyalarida (total). formatSana ostidagi daraxtga qarang: qaysi bola katta self vaqtga ega? Ehtimol Intl.DateTimeFormat har chaqiruvda qayta yaratilyapti — uni bir marta yaratib, qayta ishlatish kerak. Yoki inlining bo'lgan — qatorlar ro'yxatiga qarang.

4. Flamegraph va flame chart

.cpuprofile — raqamlar. Ko'z uchun uni rasmga aylantiramiz.

Flamegraph (alanga grafigi) — har to'rtburchak — funksiya, kengligi — total vaqti, ustidagilar — u chaqirgan funksiyalar. Vaqt tartibi yo'q: bir xil yo'llar birlashtiriladi. Keng va "yassi" tepalik — hot path.

Flame chart — gorizontal o'q vaqt: chap — dastur boshi, o'ng — oxiri. DevTools Performance panelida ko'rgansiz. Qachon nima bo'lganini ko'rsatadi (masalan, boshida makeRows, keyin summarize).

Bizning sekin.mjs profilini flamegraph sxemasida chizsak:

flowchart TB
  R["(anonim) sekin.mjs — total 351 ms"]
  R --> S["summarize — total 302 ms<br/>self 157 (18-qator: contains)"]
  R --> M["makeRows — 40 ms"]
  S --> P["parseRow — 132 ms"]
  S --> C["contains — 13 ms<br/>(qolgani inlining bilan summarize'da)"]

Bu diagramma — flamegraph emas, uning daraxt ko'rinishi (raqamlar — yuqoridagi haqiqiy profildan). Haqiqiy flamegraph'da summarize to'rtburchagi butun kenglikning ~85 % ini egallaydi, makeRows esa yonida tor ustun.

Qayerda ko'rish mumkin (hujjat bo'yicha; agent muhitida brauzer va VS Code ochilmagan — sinalmagan):

  • Chrome DevTools → Performance paneli → "Load profile" → .cpuprofile.
  • VS Code — .cpuprofile faylini ochish: o'rnatilgan ko'ruvchi jadval va flame ko'rinishini beradi.
  • chrome://inspect orqali jonli jarayon → Profiler/Performance (debug darsi).
  • speedscope.app kabi veb ko'ruvchilar .cpuprofile ni qabul qiladi (fayl brauzerda ochiladi; maxfiy kod bo'lsa — lokal versiyasini ishlating).

5. Boshqa vositalar

5.1 --prof va --prof-process

Eski, lekin hali ishlaydigan yo'l: V8 "tick" jurnali. Biz sinadik:

bash
node --prof sekin.mjs
node --prof-process isolate-0000017E7F384000-3352-v8.log

Chiqishdan (qisqartirilgan):

text
Statistical profiling result from isolate-…-v8.log, (40 ticks, 1 unaccounted, 0 excluded).

 [JavaScript]:
   ticks  total  nonlib   name
     12   30.0%   70.6%  JS: *summarize file:///C:/Users/…/sekin.mjs:22:19
      2    5.0%   11.8%  Builtin: StringAdd_CheckNone

 [Summary]:
   ticks  total  nonlib   name
     16   40.0%   94.1%  JavaScript
      3    7.5%   17.6%  GC
     23   57.5%          Shared libraries
  • Nom oldidagi belgi — kod qaysi bosqichda ishlagan: * — TurboFan optimallashtirgan, + — Maglev, ^ — Sparkplug, ~ — interpretator (Ignition). *summarize — eng tez rejimda.
  • Halol eslatma: 0.5 soniyalik dasturda atigi 40 tick chiqdi — --cpu-prof esa 252 namuna berdi. Bizning Windows mashinamizda --prof juda siyrak yozdi; Linux'da farq qilishi mumkin (sinalmagan). Qisqa dasturlar uchun --cpu-prof ishonchliroq.
  • --prof ning afzalligi: C++ va tizim kutubxonalaridagi vaqtni ham ajratadi (Shared libraries).

5.2 0x va boshqalar

  • 0x — bitta buyruq bilan flamegraph HTML yasaydi (npx 0x app.js). npm'da 6.0.0 (2026-10-23 holatiga, oxirgi o'zgarish 2025-07). Biz o'rnatmadik.
  • node:inspector moduli — profilni dastur ichidan yoqish (Profiler.start/stop), masalan faqat sekin so'rov paytida.
  • APM xizmatlari (Datadog, New Relic) — production profiling; kursning keyingi qismlarida. Eski maqolalarda Clinic.js ni ko'rasiz — uning README'si 2026-10 holatiga loyiha faol qo'llab-quvvatlanmasligini va natijalari Node'ning yangi versiyalarida noaniq bo'lishi mumkinligini aytadi. Yangi loyihada --cpu-prof dan boshlang.

6. CLI qadami: valyuta tahlil profili

Yangi holat yo'q — kanon profil yig'di, lekin kodni o'zgartirmadi. Kanon tajribasi (t47): node --cpu-prof dist/bin.js tahlil katta.csv (1 mln qator) → .cpuprofile 50 KB, 257 tugun, 601 namuna:

text
 55.3 %    544 ms  tahlilQil tahlil.js:35
 22.2 %    218 ms  runMicrotasks :0
  3.7 %     37 ms  (anonim) interface:621
  3.4 %     34 ms  (garbage collector) :0
  1.9 %     19 ms  (program) :0
  1.4 %     14 ms  csvniAjrat tahlil.js:7
  • tahlilQil — 55 %: asosiy sikl (min, max, o'rtacha).
  • runMicrotasks — 22 %: for await (const qator of rl) har qator uchun Promise yaratadi va microtask navbatidan o'tkazadi (microtask darsi).
  • csvniAjrat — 1.4 %. "CSV ajratish sekin" degan taxmin noto'g'ri edi.

Kanon bu yerda to'xtadi: readline'ning 'line' hodisasi tezroq bo'lishi mumkin — o'lchanmagan. Biz uni alohida o'lchadik (44 MB, 1 000 001 qatorli CSV, har qatordan kursni yig'ish, 7 marta mediana):

text
rl-await.mjs mediana 645 ms (min 603 max 765, n=7)
rl-event.mjs mediana 567 ms (min 536 max 611, n=7)

'line' hodisasi bilan ~12 % tez. Lekin valyuta da bu o'zgarish kiritilmadi: for await kodi qisqaroq, xatolar try/catch bilan tabiiy ushlanadi, va bu farq 1 mln qatorda 80 ms. Kundalik CBU tarixi bir necha yuz qator — farq sezilmaydi. Bu — 3-mashq.

7. Ko'p uchraydigan xatolar

Belgi Sabab Davosi
Taxmin bilan optimallashtirildi, farq yo'q Hot path boshqa joyda Avval profil
Kichik funksiya profilda "arzon" Inlining — vaqt chaqiruvchida positionTicks / qator ko'rinishi
.cpuprofile yozilmadi Dastur process.exit() yoki signal bilan uzildi Normal tugashini ta'minlang
Self kichik, total katta funksiyani qayta yozish Vaqt bolalarida Daraxtda pastga tushing
Ikki o'lchov solishtirilmaydi Har xil seans, mashina yuki Bitta seansda, bir necha marta, mediana
--prof juda kam tick Siyrak namuna (bizda Windows) --cpu-prof
Profil ostida dastur sekin Profiler narxi Absolyut vaqtni profilsiz o'lchang

8. Mashqlar

Yechimlar kurs/mashqlar/24/47-cpu-profil/ da.

1-mashq (oson): to'ldiring

  • Funksiyaning faqat o'zida o'tgan vaqt —
  • Funksiya va u chaqirganlar bilan birga —
  • Profilni yozadigan Node bayrog'i — --
  • Flamegraph'da to'rtburchak kengligi nimani bildiradi?
  • Kichik funksiya vaqtining chaqiruvchiga yozilishiga sabab —
Yechim
  • self — namuna aynan shu funksiyada.
  • total — self + bolalarining total'i.
  • cpu-prof — .cpuprofile JSON yozadi.
  • vaqt — total vaqt (tartib emas — u flame chart'da).
  • inlining — TurboFan kichik funksiyani chaqiruvchi ichiga qo'yadi.

2-mashq (o'rta): hot path'ni toping

Mini-profil uchun hotPath(profile) funksiyasini yozing: (root) dan boshlab har qadamda total'i eng katta bolaga tushadi va funksiya nomlari zanjirini qaytaradi ("a → b → c"). Darsdagi total hisobini qayta ishlating. Toza JS — saytda ham sinang.

Yechim
js
function hotPath(profile) {
  const self = new Map();
  profile.samples.forEach((id, i) => {
    self.set(id, (self.get(id) ?? 0) + profile.timeDeltas[i]);
  });
  const byId = new Map(profile.nodes.map((n) => [n.id, n]));
  const total = (id) =>
    (self.get(id) ?? 0) +
    byId.get(id).children.reduce((sum, c) => sum + total(c), 0);

  const path = [];
  let node = profile.nodes[0];
  while (node.children.length > 0) {
    const next = node.children
      .map((id) => byId.get(id))
      .reduce((a, b) => (total(b.id) > total(a.id) ? b : a));
    path.push(next.callFrame.functionName);
    node = next;
  }
  return path.join(" → ");
}

const fn = (functionName) => ({ functionName });
const profile = {
  nodes: [
    { id: 1, callFrame: fn("(root)"), children: [2, 5] },
    { id: 2, callFrame: fn("summarize"), children: [3, 4] },
    { id: 3, callFrame: fn("parseRow"), children: [] },
    { id: 4, callFrame: fn("contains"), children: [] },
    { id: 5, callFrame: fn("makeRows"), children: [] },
  ],
  samples: [2, 3, 3, 4, 4, 4, 5, 5, 3, 4],
  timeDeltas: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
};
console.log(hotPath(profile));

Konsolda:

text
summarize → contains

summarize total 8 (makeRows 2), uning ichida contains 4 > parseRow 3. Haqiqiy vositalar (DevTools'ning "Heavy (Bottom Up)" va "Tree" ko'rinishlari) shu ikki yo'nalishda — yuqoridan va pastdan — ko'rsatadi.

3-mashq (qiyin): for await mi, 'line' hodisasimi?

Kanon savoli: readline ni for await o'rniga 'line' hodisasi bilan o'qish tezroqmi? Ikkita fayl yozing — har biri katta.csv dagi qatorlarni sanaydi va 5-ustun (kurs) yig'indisini chiqaradi. CSV yasovchi skript ham yozing (1 mln qator). Har birini 7 marta alohida jarayonda ishga tushirib, medianani solishtiring. Blok Node uchun; o'lchov vaqtga bog'liq — natijangiz boshqacha bo'ladi.

Yechim

'line' hodisasi bilan o'qish (rl-event.mjs):

js
import { createReadStream } from "node:fs";
import { createInterface } from "node:readline";
import { once } from "node:events";

let n = 0;
let sum = 0;
const rl = createInterface({
  input: createReadStream("katta.csv"),
  crlfDelay: Infinity,
});
rl.on("line", (line) => {
  n++;
  sum += Number(line.split(",")[4]) || 0;
});
await once(rl, "close");
console.log(n, sum.toFixed(0));

rl-await.mjs — xuddi shu, faqat for await (const line of rl) { … }. Ikkalasi bir xil natija berdi: 1000001 11497995554 (sarlavha qatori ham sanaladi, uning kursi NaN → || 0). Bizning o'lchov (Node 24.21.0, Windows 11): for await 645 ms, 'line' 567 ms — ~12 % tez.

Nega? for await har qator uchun async iterator'ning next() Promise'ini yaratadi va hal qiladi — kanon profilidagi runMicrotasks 22 % aynan shu. Hodisa esa oddiy sinxron callback. Narxi: hodisa ichidagi xato for await dagidek try/catch ga tushmaydi, oqimni to'xtatish (break) ham qiyinroq. valyuta uchun 80 ms/1 mln qator — qulaylik ustun. Yechim fayllari: rl-await.mjs, rl-event.mjs, csv.mjs, vaqt.mjs.

4-mashq: CLI qadami

valyuta uchun profil yig'ing. Qadamlar. (1) 1 mln qatorli CSV yasang (sarlavha: sana,kod,nomi,nominal,kurs,farq). (2) npm run build, keyin node --cpu-prof --cpu-prof-dir=prof dist/bin.js tahlil katta.csv; (3) darsdagi tahlil skripti bilan top-5 ni chiqaring; (4) agar imkoningiz bo'lsa — .cpuprofile ni DevTools yoki VS Code'da oching va flamegraph'da runMicrotasks ni toping. Kodni o'zgartirmang, commit kerak emas.

Yechim

Kanon natijasi «CLI qadami» bo'limida: tahlilQil ~55 %, runMicrotasks ~22 %. Sizda foizlar yaqin, millisekundlar boshqa bo'ladi. Agar top'da csvniAjrat katta chiqsa — CSV'ingizda qo'shtirnoqli maydonlar ko'p ("…"), ajratish murakkablashgan. prof/ ni .gitignore ga qo'shing — profil fayllari repozitoriyga kerak emas.

9. Real ishda

  • Serverlarda sekin endpoint — --cpu-prof bilan lokal yuk ostida (autocannon kabi vosita bilan) yoki production'da APM xizmati orqali.
  • "Avval o'lcha" — eng muhim odat: profil ko'rsatmagan joyni optimallashtirmang.
  • Event loop bloklash (oldingi dars) va CPU profil birga: kechikish bor → profil qaysi funksiya bloklayotganini ko'rsatadi.
  • Intervyu savollari: "Node ilovasi sekin — qayerdan boshlaysiz?", "Self va total time farqi?", "Flamegraph qanday o'qiladi?".

Xulosa

  • node --cpu-prof → .cpuprofile (JSON: nodes, samples, timeDeltas, positionTicks).
  • Self — funksiyaning o'zi, total — bolalari bilan; hot path — total bo'yicha eng og'ir zanjir.
  • Inlining kichik funksiya vaqtini chaqiruvchiga yozadi — qator darajasida tekshiring (biz ko'rdik: contains 3 %, uning qatori 30 %).
  • Flamegraph — kenglik = vaqt, flame chart — o'q = vaqt tartibi; DevTools/VS Code'da ko'rish — sinalmagan.
  • Kanon: valyuta tahlil da runMicrotasks 22 %; 'line' hodisasi 645 → 567 ms, lekin kodga kiritilmadi.

Keyingi dars: Memory leak'ni topish: heap snapshot — xotira sekin o'sib borsa, ikki snapshot farqidan aybdorni topish.

Manbalar

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Node.js CPU profiling: --cpu-prof, flamegraph va hot path'ni topish — IlmHamroh