React Profiler — sekin componentlarni topish

~15 daq · React · Performance

Muammodan boshlaylik

Foydalanuvchilar shikoyat qilyapti: "Filtr tugmasini bossam, sahifa bir soniya qotib qoladi". Siz kodga qaraysiz: 40 ta komponent, hammasi oddiyga o'xshaydi. Qaysi biri sekin?

Taxmin qilib boshlaysiz: bu yerga memo, u yerga useMemo, mana bu funksiyaga useCallback... Bir soatdan keyin kod murakkablashdi, sahifa esa hali ham sekin. Chunki muammo siz o'ylagan joyda emas edi.

Performance optimizatsiyasining birinchi qoidasi: avval o'lcha, keyin tuzat. React buning uchun maxsus vosita beradi — Profiler.


React DevTools o'rnatish

Brauzer kengaytmasi: React Developer Tools (Chrome, Firefox, Edge). O'rnatgandan keyin DevTools da ikki yangi tab paydo bo'ladi:

  • ⚛ Components — komponentlar daraxti, props, state, hook lar
  • ⚛ Profiler — render vaqtlarini yozib olish

Birinchi qadam: render larni ko'rish

Components tab → ⚙ sozlamalar → "Highlight updates when components render" ni yoqing.

Endi har bir render qilingan komponent ekranda rangli ramka bilan yonib o'chadi:

  • Ko'k/yashil — kamdan-kam render
  • Sariq/qizil — tez-tez render

Qidiruv maydoniga yozing. Agar har harfda butun sahifa yonib o'chsa — muammo topildi: keraksiz render lar (67–68-darslar).


Profiler bilan yozib olish

  1. Profiler tabini oching
  2. ⏺ (Record) tugmasini bosing
  3. Sekin amalni bajaring — filtr tugmasini bosing
  4. ⏹ (Stop) ni bosing

Commit lar

Yuqori o'ng burchakda — commit lar ustunlari. Har bir commit — React ning DOM ni bir marta yangilashi (67-dars). Ustun balandligi va rangi — shu commit qancha vaqt olgani:

▁ ▁ █ ▁ ▂ ▁
    ↑
    sekin commit — 340 ms

Eng baland ustunni tanlang.

Flamegraph — olov grafigi

App (2.1ms of 340ms)
├── Header (0.3ms)
├── Filtrlar (1.2ms)
└── MahsulotRoyxati (336ms) ████████████████████████████
    ├── MahsulotKartochka (0.6ms)
    ├── MahsulotKartochka (0.7ms)
    ├── ... × 500
  • Har bir chiziq — komponent; kengligi — u va bolalarining render vaqti
  • Rang: sariq/qizil — sekin, ko'k/yashil — tez, kulrang — bu commit da render bo'lmagan
  • "2.1ms of 340ms" — komponentning o'zi 2.1 ms, bolalari bilan birga 340 ms

Bu misolda aybdor aniq: MahsulotRoyxati — 500 ta kartochka.

Ranked — tartiblangan ro'yxat

Flamegraph yonidagi Ranked ko'rinish — komponentlarni o'z render vaqti bo'yicha tartiblaydi. Eng sekini tepada.

"Why did this render?"

Profiler sozlamalari (⚙) → "Record why each component rendered while profiling" ni yoqing. Endi komponentni tanlasangiz, o'ng panelda sababi ko'rinadi:

Sabab Ma'nosi Mumkin bo'lgan yechim
The parent component rendered Ota-ona render bo'ldi State ni pastga tushirish, memo (67–68-darslar)
Props changed: (onSelect) Prop o'zgardi Har renderda yangi funksiya? → useCallback
Props changed: (filtr) Har renderda yangi obyekt? → useMemo yoki konstanta
Hook 2 changed 2-hook (state) o'zgardi Haqiqiy o'zgarish yoki keraksiz setState?
Context changed Context qiymati o'zgardi Context ni bo'lish, value ni memo qilish

Bu ma'lumot taxmin qilishni butunlay to'xtatadi.


Profiler komponenti — koddan o'lchash

Ba'zan vaqtni dasturiy ravishda o'lchash kerak (masalan, analitikaga yuborish):

import { Profiler } from 'react';

function onRender(id, phase, actualDuration, baseDuration) {
  if (actualDuration > 16) {
    console.warn(`${id} (${phase}): ${actualDuration.toFixed(1)} ms`);
  }
}

<Profiler id="MahsulotRoyxati" onRender={onRender}>
  <MahsulotRoyxati />
</Profiler>
Parametr Ma'nosi
id Profiler nomi
phase 'mount' (birinchi) yoki 'update' / 'nested-update'
actualDuration Shu commit da render ga ketgan vaqt (memo bilan o'tkazib yuborilganlar hisobga olinmaydi)
baseDuration Memo siz butun daraxtni render qilish uchun taxminiy vaqt

actualDuration va baseDuration ni solishtirib, memoizatsiya qancha foyda berayotganini ko'rish mumkin.

[!INFO] Nega 16 ms? Ekran sekundiga 60 marta yangilanadi: 1000 / 60 ≈ 16.7 ms. Agar bitta yangilanish shundan ko'p vaqt olsa, brauzer kadrni o'tkazib yuboradi va foydalanuvchi "qotish" ni sezadi. 120 Hz ekranlarda chegara yanada qattiqroq — ~8 ms.


Muhim: development va production

Development rejimida React ancha sekinroq ishlaydi: qo'shimcha tekshiruvlar, ogohlantirishlar, Strict Mode da ikki marta render (84-dars). Development da 200 ms bo'lgan narsa production da 40 ms bo'lishi mumkin.

  • Qaysi komponent sekinligini topish uchun — development da Profiler yetarli (nisbatlar to'g'ri)
  • Haqiqiy raqamlar uchun — production build ni o'lchang:
npm run build
npm run preview

Chrome Performance tab

React Profiler faqat React render larini ko'rsatadi. Muammo boshqa joyda bo'lishi mumkin: og'ir JavaScript hisob-kitob, katta DOM, layout, rasm yuklanishi. Kengroq ko'rinish uchun — Chrome DevTools → Performance:

  1. ⚙ → CPU: 4× slowdown — o'rtacha telefonni taqlid qilish (sizning kompyuteringiz foydalanuvchilarnikidan ancha tez)
  2. Record → amal → Stop
  3. Main qatorida qizil uchburchakli uzun vazifalar (Long Tasks, 50 ms dan ortiq) — asosiy muammolar

Shuningdek Lighthouse tab — sahifa yuklanishi metrikalari (LCP, INP, CLS).


Optimizatsiya jarayoni

1. Muammoni qayta hosil qil       → aniq amal: "filtr bosilganda"
2. O'lcha                          → Profiler, CPU 4× slowdown
3. Aybdorni top                    → Flamegraph, Ranked, "Why did this render?"
4. Bitta o'zgarish kirit           → state ni pastga, memo, virtualizatsiya...
5. Qayta o'lcha                    → yaxshilandimi? yo'q bo'lsa — qaytar

[!TIP] Bir vaqtda faqat bitta o'zgarish kiriting va har biridan keyin o'lchang. Aks holda qaysi o'zgarish yordam berganini bilmaysiz — va keraksiz murakkablikni kodda qoldirasiz. Yordam bermagan optimizatsiyani olib tashlang.


Nima uchun shunday?

Nima uchun tajribali dasturchilar ham sekin joyni taxmin qila olmaydi?

Chunki zamonaviy kompyuterlar va brauzerlar intuitsiyaga zid ishlaydi. 1000 ta elementli massivni filter qilish — bir necha mikrosoniya, ya'ni deyarli bepul. Shu bilan birga bitta noto'g'ri joylashgan setState butun daraxtni har harfda render qilishi, yoki katta rasm layout ni qayta hisoblashga majburlashi mumkin. Odamlar "murakkab ko'ringan" kodni sekin deb o'ylaydi, lekin sekinlik ko'pincha oddiy ko'ringan joyda bo'ladi. Donald Knut ning mashhur iborasi bor: "Muddatidan oldingi optimizatsiya — barcha yovuzliklarning ildizi". Profiler bu tamoyilni amalga oshiradi: siz faqat haqiqatan sekin joyni, isbotlangan holda tuzatasiz.


Xulosa

Eslab qoling:

  • Avval o'lcha, keyin tuzat — taxmin qilma
  • React DevTools: Highlight updates — keraksiz render larni ko'rish
  • Profiler: Record → amal → Stop; commit lar, Flamegraph, Ranked
  • "Why did this render?" — ota-ona, props, hook, Context
  • <Profiler id onRender> — koddan o'lchash; 16 ms — bitta kadr chegarasi
  • Development sekinroq; haqiqiy raqamlar — production build da
  • Chrome Performance (CPU 4× slowdown) va Lighthouse — kengroq tahlil
  • Bitta o'zgarish → qayta o'lchash; yordam bermaganini olib tashlash

Keyingi dars

72-dars: Bundle Size — tahlil qilish, optimizatsiya