IlmHamroh
Python kursi/Miqyos va unumdorlik2/10-dars18 daqiqa
Mundarija (22)

29.2-dars: Profiling amaliyoti

29-QISM — MIQYOS VA UNUMDORLIK · 2-dars


1. Kirish va motivatsiya

Unumdorlikni o'lchash 29.1-bob tizim sekin ekanini ko'rsatadi — lekin qayerda sekin? 10,000 qatorli kodning qaysi funksiyasi vaqtni yeydi? Har funksiyani qo'lda o'lchash — imkonsiz. Dasturchilar bu yerda yana taxminga tushadi ("bu funksiya sekin bo'lsa kerak") va ko'pincha xato qiladi (haqiqiy "bottleneck" — to'siq boshqa joyda). Profiling buni hal qiladi: dasturni ishga tushirar ekan, har funksiya qancha vaqt olgani, necha marta chaqirilgani avtomatik yozadi. Natija — aniq rasm: qaysi funksiya vaqtning 80% ini yeydi (issiq nuqta). Profiling — sekinlikning aniq manzilini topish.

Profiling — dastur bajarilishi davomida har qismning (funksiya, qator) resurs sarfini o'lchash: CPU profiling (qaysi funksiya qancha vaqt — cProfile), line profiling (qaysi qator — line_profiler), xotira profiling (qaysi qism xotira yeydi — memory_profiler, tracemalloc), statistik profiling (namunalar — py-spy). Natija: bottleneck (to'siq — eng ko'p vaqt/resurs oladigan joy), chaqiruvlar grafi (kim kimni chaqiradi), issiq nuqtalar. Prinsip: profiling → bottleneck → optimallashtir (80/20 — 28.4). Bu o'lchash 29.1-bob ni funksiya darajasiga chuqurlashtiradi. Profiling — sekinlikning manbaini topish. To'siqni topish — optimizatsiya yo'li.

Real vaziyat. Bir dastur sekin edi — jamoa ma'lumot qayta ishlash algoritmini optimallashtirmoqchi edi (taxmin, ko'p ish). cProfile ishga tushirildi: ma'lum bo'ldi, vaqtning 70% i bir kichik funksiyada — u har element uchun JSON'ni qayta tahlil qilardi (keshlanmagan). Funksiya keshlandi (bir marta tahlil), dastur 5 barobar tez bo'ldi. Algoritm yaxshi edi, muammo kutilmagan joyda (kichik funksiya). Profiling — haqiqiy to'siqni ko'rsatdi.

Bu darsda profiling amaliyotini o'rganamiz.

Bu darsda:

  • Profiling nima
  • CPU profiling (cProfile)
  • Line profiling (qator darajasi)
  • Xotira profiling
  • Bottleneck (to'siq) topish
  • Deterministik vs statistik profiling
  • Profiling amaliyoti
  • Amaliy: profiling modeli

ℹ Misollar chaqiruv/amal sonini (deterministik) o'lchaydi — vaqt emas.


2. Nazariya — chuqur tushuntirish

2.1. Profiling nima

Qayerda sekin — aniq topish:

O'lchash (29.1): tizim sekin (qanchalik)
Profiling: QAYERDA sekin (qaysi funksiya, qator)

har funksiya: qancha vaqt, necha marta chaqirilgan
   → bottleneck (eng ko'p vaqt — to'siq)

Profiling — dastur ishlar ekan, har qismning (funksiya, qator) resurs sarfini avtomatik o'lchash: qaysi funksiya qancha vaqt oladi, necha marta chaqiriladi. Sabab: o'lchash 29.1-bob tizim sekinligini ko'rsatadi, lekin qayerda noma'lum (katta kodda); profiling aniq joyni (bottleneck — to'siq) topadi (taxmin emas). Natija: eng ko'p vaqt/resurs oladigan funksiya (80/20 — kam joy, ko'p vaqt). Profiling — sekinlikning manzilini topish. Bu o'lchash 29.1-bob ni chuqurlashtiradi (funksiya darajasi). Profiling — qayerda sekin. To'siqni topish.

2.2. CPU profiling (cProfile)

Qaysi funksiya qancha vaqt:

python
import cProfile
cProfile.run("main()")
# natija:
#   ncalls  tottime  cumtime  function
#   1000    0.500    0.800    parse_json
#   1       0.010    0.900    main
# tottime — funksiyaning o'zida, cumtime — ichki chaqiruvlar bilan

CPU profiling (cProfile — Python standart) — har funksiya qancha vaqt oladi va necha marta chaqiriladi: ncalls (chaqiruvlar soni), tottime (funksiyaning o'zida sarflangan vaqt — ichki chaqiruvsiz), cumtime (kumulyativ — ichki chaqiruvlar bilan). Foydali: tottime — funksiyaning o'zi sekin (optimallashtiriladigan), cumtime — funksiya + ichkilar (umumiy ta'sir). Sabab: qaysi funksiya vaqtni yeydi — aniq ko'rinadi (tartiblab — eng og'ir yuqorida). cProfile deterministik (har chaqiruvni yozadi — biroz sekinlashtiradi). CPU profiling — funksiya vaqtlarini ko'rish. tottime — eng muhim.

2.3. Line profiling (qator darajasi)

Qaysi qator sekin:

python
# line_profiler — funksiya ichida qaysi QATOR sekin
@profile
def hisobla(data):
    natija = []
    for x in data:            # 30% vaqt
        y = qimmat_amal(x)    # 60% vaqt  ← bottleneck
        natija.append(y)      # 10% vaqt
    return natija

Line profiling (line_profiler) — funksiya ichida qaysi qator sekin: har qator qancha vaqt oladi, necha marta bajariladi. Sabab: cProfile funksiya darajasida (qaysi funksiya sekin), lekin funksiya ichida qaysi qator noma'lum — line profiler aniq qatorni ko'rsatadi (masalan bir sikl ichidagi qimmat amal). Bu chuqurroq (funksiya → qator). Sekinroq (har qatorni o'lchash), shuning uchun aniqlangan funksiyaga qo'llanadi (cProfile'dan keyin). Line profiling — qator darajasidagi to'siq. Funksiyadan qatorga.

2.4. Xotira profiling

Xotira qayerda yeyiladi:

python
import tracemalloc
tracemalloc.start()
# ... kod ...
joriy, eng_yuqori = tracemalloc.get_traced_memory()
# eng ko'p xotira olgan joylar (top)

# memory_profiler — qator bo'yicha xotira

Xotira profiling — dastur xotira sarfini o'lchash (CPU emas): tracemalloc (standart — xotira ajratishlarini kuzatadi, eng ko'p olgan joylar), memory_profiler (qator bo'yicha xotira o'sishi). Sabab: ba'zi muammo CPU emas, xotira (xotira oqishi — memory leak, katta obyektlar, keraksiz nusxalar — 29.9). Belgi: xotira asta o'sadi (leak), yoki birdan ko'p (katta ma'lumot bir vaqtda). Xotira profiling — xotira muammolarini topish. Bu 29.9 (xotira optimizatsiyasi) bilan bog'liq. Xotira profiling — CPU emas, xotira. Xotira ham resurs.

2.5. Bottleneck (to'siq) topish

Eng ko'p ta'sir joy:

Bottleneck (to'siq) — eng ko'p vaqt/resurs oladigan joy
   80/20: kodning 20% i vaqtning 80% ini yeydi

profiling → tartiblab (eng og'ir yuqorida)
   → eng og'irni optimallashtir (eng katta ta'sir)

Bottleneck (to'siq) — dasturning eng ko'p vaqt/resurs oladigan qismi (suv trubadagi tor joy kabi — butun oqimni sekinlashtiradi): 80/20 qoidasi (kodning 20% i vaqtning 80% ini yeydi — kam joy, katta ta'sir). Profiling bottleneckni ko'rsatadi (tartiblab — eng og'ir yuqorida). Sabab: bottleneckni optimallashtirish — eng katta foyda (28.4 — o'lcha, eng katta ta'sirni tuzat); boshqa joylarni optimallashtirish — kam foyda (vaqtning 80% i bottleneckda). Bir bottleneck tuzatilsa — keyingisi paydo bo'ladi (iterativ). Bottleneck — optimizatsiya nishoni. Eng og'ir — eng katta imkoniyat.

2.6. Deterministik vs statistik profiling

Ikki profiling turi: Deterministik (cProfile — har funksiya chaqiruvini yozadi — aniq, lekin dasturni sekinlashtiradi — overhead; rivojlanishda, aniq tahlil); Statistik (py-spy, perf — namuna oladi — vaqti-vaqti bilan "hozir qaysi funksiyada?" so'raydi — kam overhead, prodda ishlaydi, lekin aniq emas — taxminiy). Farqi: deterministik aniq (har chaqiruv), lekin sekin; statistik tez (namuna), lekin taxminiy. Statistik prodda (ishlayotgan tizimda — 28.10 monitoring kabi), deterministik rivojlanishda (chuqur tahlil). Har biri — o'z o'rni. Deterministik — aniq/sekin, statistik — taxminiy/tez.

2.7. Profiling amaliyoti

Profiling amaliyotlari: avval profiling (28.4 — o'lchamasdan optimallashtirma); real sharoit (real ma'lumot — 29.1, kichik ma'lumot boshqacha); cProfile avval (funksiya darajasi), keyin line profiler (qator — aniqlangan funksiya); bottleneckdan boshla (eng og'ir — 80/20); iterativ (bir bottleneck → tuzat → qayta profiling → keyingisi); qayta o'lcha (optimallashtirishdan keyin — haqiqatan yaxshilandimi?); prodda statistik (py-spy — kam overhead). Yomon: profilingsiz optimizatsiya (taxmin), mikro-optimizatsiya (kichik joy). Yaxshi profiling — avval, real, bottleneckdan. Amaliyot — samarali profiling. Profiling → to'siq → tuzat → qayta.

2.8. Profiling — sekinlikning aniq manzili

Profiling asosiy g'oyasi — sekinlikning aniq manzilini (taxmin emas) topish: dastur qayerda vaqt/resurs yeydi — raqamlar bilan (funksiya, qator). Bu o'lchash (29.1 — tizim sekin) ni chuqurlashtiradi (aynan qayerda). "O'lcha → profiling → bottleneck → optimallashtir → qayta o'lcha" (ilmiy usul). Profiling optimizatsiyani yo'naltiradi (eng katta ta'sirga — 80/20), taxminni yo'q qiladi (dasturchi intuitsiyasi noto'g'ri — 29.1). Bu kesh 29.3-bob, miqyoslash 29.6-bob qarorlarining asosi (qayerda keshlash, nimani optimallashtirish). "Avval profiling qil" — muhandislik prinsipi. Profiling — sekinlikni ko'rinadigan qilish. Aniq manzil — to'g'ri optimizatsiya.


3. Tez ma'lumotnoma

python
# CPU PROFILING (cProfile — funksiya darajasi):
import cProfile
cProfile.run("main()")
# ncalls (chaqiruvlar), tottime (o'zida), cumtime (ichkilar bilan)

# yoki buyruq: python -m cProfile -s tottime script.py

# LINE PROFILING (line_profiler — qator darajasi):
# @profile dekorator + kernprof -l -v script.py

# XOTIRA (tracemalloc):
import tracemalloc
tracemalloc.start()
# ... kod ...
joriy, eng_yuqori = tracemalloc.get_traced_memory()
top = tracemalloc.take_snapshot().statistics("lineno")

# STATISTIK (prod): py-spy record -o profil.svg --pid PID

# BOTTLENECK: 80/20 (20% kod → 80% vaqt)
# JARAYON: profiling → bottleneck → optimallashtir → qayta

# TURLARI:
# deterministik (cProfile) — aniq, sekin (dev)
# statistik (py-spy) — taxminiy, tez (prod)

Profiling xulosasi

Profiling — qayerda sekin (funksiya, qator — aniq)
cProfile (CPU — ncalls, tottime, cumtime) · line_profiler (qator)
tracemalloc (xotira) · bottleneck (to'siq — 80/20)
Deterministik (aniq, sekin) vs statistik (tez, prod)
Profiling → bottleneck → optimallashtir → qayta o'lcha

4. Batafsil misollar

Misollar chaqiruv/amal sonini (deterministik) o'lchaydi — vaqt emas.

Misol 1 — Funksiya profiling (chaqiruvlar, amal)

python
"""Profiling: har funksiyaning amal soni (qaysi funksiya og'ir)."""


class Profiler:
    def __init__(self) -> None:
        self.hisobot: dict = {}

    def qayd(self, funksiya: str, amallar: int) -> None:
        if funksiya not in self.hisobot:
            self.hisobot[funksiya] = {"chaqiruvlar": 0, "amallar": 0}
        self.hisobot[funksiya]["chaqiruvlar"] += 1
        self.hisobot[funksiya]["amallar"] += amallar

    def tartiblab(self) -> list:
        return sorted(self.hisobot.items(), key=lambda x: x[1]["amallar"], reverse=True)


def main() -> None:
    prof = Profiler()

    # simulyatsiya: funksiyalar turli amal qiladi
    for _ in range(100):
        prof.qayd("parse_json", 50)      # og'ir (100*50)
    for _ in range(10):
        prof.qayd("hisobla", 20)
    for _ in range(1):
        prof.qayd("main", 5)

    print("=== 1. Profiling hisoboti (amal bo'yicha) ===")
    for funksiya, ma in prof.tartiblab():
        print(f"  {funksiya}: {ma['chaqiruvlar']} chaqiruv, {ma['amallar']} amal")

    print("\n=== 2. Eng og'ir funksiya (bottleneck) ===")
    eng = prof.tartiblab()[0]
    print(f"  {eng[0]}: {eng[1]['amallar']} amal")

    print("\n=== 3. Ta'sir foizi ===")
    jami = sum(m["amallar"] for _, m in prof.hisobot.items())
    print(f"  {eng[0]}: {round(eng[1]['amallar'] / jami * 100)}% (80/20)")

    print("\n=== 4. Optimizatsiya nishoni ===")
    print(f"  {eng[0]} ni tuzat (eng katta ta'sir)")
    print("  boshqalarni — kam foyda")
    print("  ⭐ Profiling — bottleneckni ko'rsatadi")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Profiling hisoboti (amal bo'yicha) ===
  parse_json: 100 chaqiruv, 5000 amal
  hisobla: 10 chaqiruv, 200 amal
  main: 1 chaqiruv, 5 amal

=== 2. Eng og'ir funksiya (bottleneck) ===
  parse_json: 5000 amal

=== 3. Ta'sir foizi ===
  parse_json: 96% (80/20)

=== 4. Optimizatsiya nishoni ===
  parse_json ni tuzat (eng katta ta'sir)
  boshqalarni — kam foyda
  ⭐ Profiling — bottleneckni ko'rsatadi

Nima ko'rsatdi: 2.1, 2.2, 2.5-bo'limlar.

Misol 2 — tottime vs cumtime

python
"""tottime vs cumtime: funksiyaning o'zi vs ichki chaqiruvlar bilan."""


def profil_hisobla(chaqiruvlar: dict) -> dict:
    # chaqiruvlar: funksiya → (o'z_amali, ichki_funksiyalar)
    natija = {}
    for f, (oz_amal, ichkilar) in chaqiruvlar.items():
        cumtime = oz_amal + sum(chaqiruvlar[i][0] for i in ichkilar)
        natija[f] = {"tottime": oz_amal, "cumtime": cumtime}
    return natija


def main() -> None:
    # main → hisobla → parse (chaqiruvlar zanjiri)
    chaqiruvlar = {
        "parse": (500, []),           # o'zida 500
        "hisobla": (100, ["parse"]),  # o'zida 100 + parse
        "main": (10, ["hisobla"]),    # o'zida 10 + hisobla (+ parse)
    }

    profil = profil_hisobla(chaqiruvlar)

    print("=== 1. tottime (funksiyaning o'zida) ===")
    for f, p in profil.items():
        print(f"  {f}: {p['tottime']}")

    print("\n=== 2. cumtime (ichkilar bilan) ===")
    for f, p in profil.items():
        print(f"  {f}: {p['cumtime']}")

    print("\n=== 3. Farq ===")
    print(f"  parse: tottime={profil['parse']['tottime']}, cumtime={profil['parse']['cumtime']} (barobar)")
    print(f"  main: tottime={profil['main']['tottime']}, cumtime={profil['main']['cumtime']} (katta farq)")

    print("\n=== 4. Qaysi muhim ===")
    print("  tottime — funksiyaning o'zi sekin (parse — optimallashtir)")
    print("  cumtime — umumiy ta'sir (main — hammasi)")
    print("  ⭐ tottime — optimallashtiriladigan joy")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. tottime (funksiyaning o'zida) ===
  parse: 500
  hisobla: 100
  main: 10

=== 2. cumtime (ichkilar bilan) ===
  parse: 500
  hisobla: 600
  main: 110

=== 3. Farq ===
  parse: tottime=500, cumtime=500 (barobar)
  main: tottime=10, cumtime=110 (katta farq)

=== 4. Qaysi muhim ===
  tottime — funksiyaning o'zi sekin (parse — optimallashtir)
  cumtime — umumiy ta'sir (main — hammasi)
  ⭐ tottime — optimallashtiriladigan joy

Nima ko'rsatdi: 2.2-bo'lim.

Misol 3 — Line profiling (qator darajasi)

python
"""Line profiling: funksiya ichida qaysi qator eng ko'p amal (bottleneck)."""


def line_profil(qatorlar: dict) -> dict:
    jami = sum(qatorlar.values())
    return {qator: {"amal": amal, "foiz": round(amal / jami * 100)}
            for qator, amal in qatorlar.items()}


def main() -> None:
    # funksiya ichidagi qatorlar (amal soni)
    qatorlar = {
        "natija = []": 1,
        "for x in data": 100,
        "y = qimmat_amal(x)": 900,   # bottleneck
        "natija.append(y)": 100,
    }

    profil = line_profil(qatorlar)

    print("=== 1. Qator profiling ===")
    for qator, p in profil.items():
        print(f"  {qator}: {p['amal']} amal ({p['foiz']}%)")

    print("\n=== 2. Eng og'ir qator (bottleneck) ===")
    eng = max(profil.items(), key=lambda x: x[1]["amal"])
    print(f"  '{eng[0]}': {eng[1]['foiz']}%")

    print("\n=== 3. Aniqlik ===")
    print("  cProfile: funksiya sekin")
    print("  line profiler: qaysi QATOR sekin (aniqroq)")

    print("\n=== 4. Optimizatsiya ===")
    print(f"  '{eng[0]}' — bu qatorni tuzat (keshlash, tez amal)")
    print("  ⭐ Line profiling — qator darajasidagi to'siq")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Qator profiling ===
  natija = []: 1 amal (0%)
  for x in data: 100 amal (9%)
  y = qimmat_amal(x): 900 amal (82%)
  natija.append(y): 100 amal (9%)

=== 2. Eng og'ir qator (bottleneck) ===
  'y = qimmat_amal(x)': 82%

=== 3. Aniqlik ===
  cProfile: funksiya sekin
  line profiler: qaysi QATOR sekin (aniqroq)

=== 4. Optimizatsiya ===
  'y = qimmat_amal(x)' — bu qatorni tuzat (keshlash, tez amal)
  ⭐ Line profiling — qator darajasidagi to'siq

Nima ko'rsatdi: 2.3-bo'lim.

Misol 4 — Iterativ profiling (bottleneck ketma-ketligi)

python
"""Iterativ: bir bottleneck tuzatilsa, keyingisi paydo bo'ladi (takroriy)."""


def eng_ogir(qadamlar: dict) -> tuple:
    f = max(qadamlar, key=lambda k: qadamlar[k])
    return f, qadamlar[f]


def main() -> None:
    qadamlar = {"parse": 700, "hisobla": 150, "saqlash": 100, "javob": 50}

    print("=== 1. Boshlang'ich profiling ===")
    for f, amal in sorted(qadamlar.items(), key=lambda x: x[1], reverse=True):
        print(f"  {f}: {amal}")

    print("\n=== 2. 1-bottleneck (parse) ===")
    f1, amal1 = eng_ogir(qadamlar)
    print(f"  {f1}: {amal1} — optimallashtir (keshlash)")
    qadamlar[f1] = 50   # keshlandi

    print("\n=== 3. Qayta profiling (parse tuzatildi) ===")
    for f, amal in sorted(qadamlar.items(), key=lambda x: x[1], reverse=True):
        print(f"  {f}: {amal}")

    print("\n=== 4. 2-bottleneck (endi hisobla) ===")
    f2, amal2 = eng_ogir(qadamlar)
    print(f"  {f2}: {amal2} — endi eng og'ir")
    print("  bir to'siq tuzatildi → keyingisi paydo (iterativ)")
    print("  ⭐ Profiling — takroriy (bottleneck ketma-ketligi)")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Boshlang'ich profiling ===
  parse: 700
  hisobla: 150
  saqlash: 100
  javob: 50

=== 2. 1-bottleneck (parse) ===
  parse: 700 — optimallashtir (keshlash)

=== 3. Qayta profiling (parse tuzatildi) ===
  hisobla: 150
  saqlash: 100
  parse: 50
  javob: 50

=== 4. 2-bottleneck (endi hisobla) ===
  hisobla: 150 — endi eng og'ir
  bir to'siq tuzatildi → keyingisi paydo (iterativ)
  ⭐ Profiling — takroriy (bottleneck ketma-ketligi)

Nima ko'rsatdi: 2.5, 2.7-bo'limlar.


5. To'g'ri va noto'g'ri tushunishlar

Noto'g'ri fikr To'g'risi
"Qaysi sekin — bilaman" Profiling (taxmin adashtiradi)
"cProfile qator ko'rsatadi" Funksiya (line profiler — qator)
"tottime = cumtime" O'zida vs ichkilar bilan
"Faqat CPU" Xotira ham (tracemalloc)
"Hamma joyni optimallashtir" Bottleneck (80/20)
"cProfile prodda" Statistik (py-spy) prodda
"Bir marta profiling" Iterativ (keyingi bottleneck)
"Profilingsiz optimizatsiya" Avval profiling

6. Keng tarqalgan xatolar va yechimlari

1. Profilingsiz optimizatsiya

python
# "bu sekin" (taxmin) → optimallashtirish             # ⚠️
cProfile.run("main()")   # avval profiling             # ✅

2. cumtime bilan adashish

python
# main cumtime katta → main sekin (yo'q)               # ⚠️
# tottime — funksiyaning o'zi (parse — haqiqiy)         # ✅

3. Kichik ma'lumot bilan profiling

python
# 10 element bilan (prod — million)                    # ⚠️
# real hajm (bottleneck boshqacha bo'lishi mumkin)      # ✅

4. cProfile'ni prodda ishlatish

python
# cProfile prodda (sekinlashtiradi)                    # ⚠️
# statistik (py-spy — kam overhead)                     # ✅

5. Bir bottleneck bilan to'xtash

python
# birni tuzatib to'xtash                               # ⚠️
# qayta profiling (keyingi bottleneck)                  # ✅

6. Xotirani e'tiborsiz

python
# faqat CPU (xotira leak ko'rinmaydi)                  # ⚠️
# tracemalloc (xotira ham)                              # ✅

7. Optimallashtirishdan keyin o'lchamaslik

python
# "tuzatdim" (haqiqatan yaxshilandimi?)                # ⚠️
# qayta profiling (tasdiqlash)                          # ✅

7. Integratsiya — bu bilim qayerda kerak bo'ladi

  • 29.1-dars (o'tilgan): O'lchash — profiling asosi
  • 29.3-dars: Kesh — bottleneckni keshlash
  • 29.9-dars: Xotira — xotira profiling
  • 28.4-dars (o'tilgan): Optimizatsiya — 80/20
  • 28.10-dars (o'tilgan): Monitoring — prodda statistik

8. Eng yaxshi amaliyotlar

  1. Avval profiling (taxmin emas).

  2. cProfile → line profiler (funksiya → qator).

  3. tottime — optimallashtiriladigan joy.

  4. Bottleneckdan boshla (80/20).

  5. Real ma'lumot (katta hajm).

  6. Iterativ (qayta profiling — keyingi to'siq).

  7. Prodda statistik (py-spy — kam overhead).

  8. Xotira ham (tracemalloc).


9. Amaliy topshiriq

Vazifa 1: Bashorat qiling

python
1.  # profiling nima?
2.  # o'lchash vs profiling?
3.  # cProfile nima?
4.  # ncalls nima?
5.  # tottime nima?
6.  # cumtime nima?
7.  # tottime vs cumtime?
8.  # line profiling nima?
9.  # xotira profiling nima?
10. # bottleneck nima?
11. # deterministik vs statistik?
12. # nega iterativ?
Javoblar
  1. Qayerda sekin — funksiya/qator o'lchash
  2. O'lchash tizim, profiling qayerda
  3. CPU profiling (funksiya vaqti)
  4. Chaqiruvlar soni
  5. Funksiyaning o'zida vaqt
  6. Ichki chaqiruvlar bilan vaqt
  7. tottime o'zida, cumtime ichkilar bilan
  8. Qaysi qator sekin
  9. Xotira sarfi (tracemalloc)
  10. Eng ko'p vaqt/resurs joy (to'siq)
  11. Deterministik aniq/sekin, statistik tez/taxminiy
  12. Bir to'siq tuzatilsa keyingisi paydo

Vazifa 2: Xatolarni tuzating

python
1.  # "bu sekin" (taxmin)

2.  # main cumtime katta → main sekin

3.  # 10 element (prod million)

4.  # cProfile prodda

5.  # birni tuzatib to'xtash
Javoblar
python
1.  cProfile.run() (avval profiling)

2.  tottime (funksiya ichki vaqti)

3.  real hajm (katta)

4.  statistik (py-spy)

5.  qayta profiling (keyingi bottleneck)

Vazifa 3: Profiling

Modellang:

  1. Funksiyalar
  2. Amal
  3. Tartiblab
  4. Bottleneck

Vazifa 4: tottime/cumtime

Modellang:

  1. O'z amali
  2. Ichkilar
  3. tottime
  4. cumtime

Vazifa 5: Line profiling

Modellang:

  1. Qatorlar
  2. Amal
  3. Foiz
  4. Bottleneck

Vazifa 6: Iterativ

Modellang:

  1. Profiling
  2. 1-bottleneck
  3. Tuzat
  4. Keyingi

Vazifa 7: O'ylash

Profiling "sekinlikning aniq manzilini topish" — dasturchining taxminini raqamlar bilan almashtiradi (29.1 davomi). Nima uchun "bottleneck" (bir kichik joy vaqtning 80% ini yeydi) shunchalik keng tarqalgan naqsh (nafaqat dasturlashda — hayotda umuman), va nega "eng og'ir joydan boshlash" (80/20) intuitsiyaga zid tuyulishi mumkin (dasturchi hamma joyni bir xil yaxshilashni xohlaydi)?

Javob

Qisqa javob: "Bottleneck" (80/20 — Pareto prinsipi) keng tarqalgan, chunki: murakkab tizimlarda ish notekis taqsimlanadi — ba'zi qismlar boshqalardan ko'p ishlaydi (issiq yo'l — tez-tez chaqiriladigan kod, katta sikl, sekin I/O), qolganlar kam. Bu tabiiy (Pareto): sabab-oqibat notekis — kirim (input) ning 20% i chiqim (output) ning 80% ini beradi. Dasturda: kod ko'p (10,000 qator), lekin vaqt oz joyda to'planadi (bir necha issiq funksiya — sikl ichi, I/O). Bu hayotda umuman (Pareto asli iqtisod): boylikning 80% i odamlarning 20% ida, mijozlarning 20% i daromadning 80% ini beradi, xatolarning 20% i muammolarning 80% ini. Sabab bir xil: murakkab tizimda ta'sir notekis to'planadi (bir necha muhim omil). "Eng og'irdan boshlash" intuitsiyaga zid, chunki: (1) adolatli tuyulmaydi ("hamma joyni bir xil yaxshilash" — tabiiy, sistemali istak); (2) ko'rinar ish (ko'p kichik yaxshilash — ko'p "bajarildi" hissi, lekin kam ta'sir); (3) mikro-optimizatsiya vasvasasi (kichik joyni optimallashtirish oson, xavfsiz — lekin foydasiz); (4) bottleneck noqulay (eng og'ir joy ko'pincha eng murakkab — qo'rqinchli). Lekin haqiqat: 80% joyni yaxshilash — 20% foyda (kam ta'sir joyga ko'p ish); 20% joyni (bottleneck) yaxshilash — 80% foyda (katta ta'sir). "Eng og'irdan boshlash" — resursni (vaqt, kuch) eng katta ta'sirga yo'naltirish (samarali). Bu 28.4 (o'lcha, eng katta ta'sir) bilan bir. Muhandislik saboqlari: ta'sir notekis to'planadi (Pareto — hamma joyda); eng og'irdan boshla (80/20 — katta foyda); "hamma joyni bir xil" — intuitiv, lekin samarasiz; profiling bottleneckni ko'rsatadi (intuitsiyani to'g'rilaydi).

1. Nega bottleneck keng tarqalgan (Pareto)

Murakkab tizimda ish notekis taqsimlanadi (issiq yo'l — ko'p, qolgan — kam). Tabiiy (sabab-oqibat notekis).

2. Hayotda umuman

Boylik (20% odam → 80%), mijoz (20% → 80% daromad), xato (20% → 80% muammo). Bir prinsip (Pareto).

3. Nega intuitsiyaga zid

  • Adolatli tuyulmaydi ("hamma bir xil")
  • Ko'rinar ish (ko'p kichik — "bajarildi" hissi)
  • Mikro-optimizatsiya oson (lekin foydasiz)
  • Bottleneck noqulay (murakkab, qo'rqinchli)

4. Haqiqat (80/20)

Yondashuv Ta'sir
80% joy (kichik) 20% foyda
20% joy (bottleneck) 80% foyda

5. Muhandislik saboqlari

  1. Ta'sir notekis (Pareto — hamma joyda)
  2. Eng og'irdan boshla (80/20)
  3. "Hamma bir xil" — samarasiz
  4. Profiling bottleneckni ko'rsatadi

6. Xulosa

  1. Bottleneck — Pareto (notekis ta'sir)
  2. Hayotda umuman (boylik, mijoz, xato)
  3. Eng og'irdan (intuitsiyaga zid, lekin samarali)
  4. Profiling — to'g'ri nishon

Nimani mustahkamlaydi: 2.5, 2.7-bo'limlar.


Xulosa

Bu darsda profiling amaliyotini o'rgandik.

Eng muhim uch fikr:

  1. Profiling va CPU profiling. Profiling — dastur ishlar ekan, har qismning (funksiya, qator) resurs sarfini avtomatik o'lchash (qaysi funksiya qancha vaqt, necha marta chaqiriladi); o'lchash (29.1 — tizim sekin) ni chuqurlashtiradi (qayerda sekin — bottleneck). CPU profiling (cProfile) — har funksiya: ncalls (chaqiruvlar), tottime (funksiyaning o'zida vaqt), cumtime (ichki chaqiruvlar bilan); tottime — funksiya o'zi sekin (optimallashtiriladigan), cumtime — umumiy ta'sir.

  2. Line profiling, xotira, bottleneck. Line profiling (line_profiler) — funksiya ichida qaysi qator sekin (cProfile funksiya, line profiler qator — aniqroq, aniqlangan funksiyaga). Xotira profiling (tracemalloc, memory_profiler) — xotira sarfi (CPU emas — xotira oqishi/leak, katta obyektlar — 29.9). Bottleneck (to'siq) — eng ko'p vaqt/resurs oladigan qism (80/20 — kodning 20% i vaqtning 80% ini yeydi); profiling tartiblab ko'rsatadi, bottleneckni optimallashtirish — eng katta foyda 28.4-bob.

  3. Turlar va amaliyot. Deterministik (cProfile — har chaqiruvni yozadi — aniq, lekin sekinlashtiradi — dev) vs statistik (py-spy — namuna — kam overhead, prodda — 28.10). Amaliyot: avval profiling (taxmin emas), real sharoit (katta ma'lumot), cProfile → line profiler, bottleneckdan boshla (80/20), iterativ (bir to'siq → tuzat → qayta profiling → keyingisi), qayta o'lcha. Profiling sekinlikning aniq manzilini (taxmin emas) topadi — "o'lcha → profiling → bottleneck → optimallashtir → qayta". Bottleneck (Pareto — 80/20) keng tarqalgan naqsh (ta'sir notekis to'planadi — hayotda umuman); "eng og'irdan boshlash" intuitsiyaga zid, lekin samarali (resursni eng katta ta'sirga). Kesh 29.3-bob, miqyoslash 29.6-bob qarorlarining asosi.

Keyingi darsda kesh strategiyalarini o'rganamiz: takroriy hisoblash/so'rov natijasini saqlab, qayta ishlatish — kesh turlari, invalidatsiya, lru_cache, Redis va keshlashning tez unumdorlik yutug'i.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!