ЁЯПБ рдзрдбрд╛ 02 тАФ рдкреНрд░рд╛рдорд╛рдгрд┐рдХ benchmarking: warm-up рдлреЗрд▒реНрдпрд╛ рдЖрдгрд┐ рдЕрдиреЗрдХ heats
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 02 ┬╖ рдорд╛рдЧреЗ: lesson-01-latency-percentiles ┬╖ рдкреБрдвреЗ: lesson-03-profiling
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбрд╛ 01, рдЕрдзрд┐рдХ рдПрдХрд╛ program рдЪреНрдпрд╛ рджреЛрди versions рдЪреА рдкреНрд░рд╛рдорд╛рдгрд┐рдХ рддреБрд▓рдирд╛. рдПрдХ run рдЦреЛрдЯреЗ рдмреЛрд▓рддреЛ: рдкрд╣рд┐рд▓реЗ
runs рдердВрдб рдЕрд╕рддрд╛рдд, machine рдордзреНрдпреЗ noise рдЕрд╕рддреЛ, рдЖрдгрд┐ рдЫреЛрдЯреЗ рдмрджрд▓ рддреНрдпрд╛ noise рдордзреНрдпреЗ рд▓рдкрддрд╛рдд. рдпрд╛рд╡рд░
рдЙрдкрд╛рдп: warm up рдХрд░рд╛, рдкреБрдиреНрд╣рд╛ рдкреБрдиреНрд╣рд╛ рдЪрд╛рд▓рд╡рд╛, median рдЖрдгрд┐ рдкрд╕рд╛рд░рд╛ (spread) рд╕рд╛рдВрдЧрд╛, рдЖрдгрд┐ рдлрд╛рдпрджрд╛ рддреЗрд╡реНрд╣рд╛рдЪ рдЬрд╛рд╣реАрд░ рдХрд░рд╛
рдЬреЗрд╡реНрд╣рд╛ рддреЛ noise рдкреЗрдХреНрд╖рд╛ рдореЛрдард╛ рдЕрд╕реЗрд▓. perf/demo.py рдордзрд▓реЗ bench() рдЖрдгрд┐
perf/sim.py рдордзрд▓реЗ simulated_runs, spread рдЖрдгрд┐ verdict.
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
рдирд╡реАрди рдзрд╛рд╡рдгреНрдпрд╛рдЪреНрдпрд╛ рдмреБрдЯрд╛рдВрдореБрд│реЗ рдРрд╢реНрд╡рд░реНрдпрд╛ рдЬрд▓рдж рдзрд╛рд╡рддреЗ рдХрд╛, рд╣реЗ рджреАрдкрд┐рдХрд╛рд▓рд╛ рдЬрд╛рдгреВрди рдШреНрдпрд╛рдпрдЪреЗ рдЖрд╣реЗ. ЁЯСЯ
рдХрддрд░рд┐рдирд╛ рдЬреБрдиреНрдпрд╛ рдмреБрдЯрд╛рдВрдд рдРрд╢реНрд╡рд░реНрдпрд╛рдЪреА рд╡реЗрд│ рдПрдХрджрд╛рдЪ рдШреЗрддреЗ. рднрд▓реНрдпрд╛ рд╕рдХрд╛рд│реА рдРрд╢реНрд╡рд░реНрдпрд╛ рдердВрдб рдЖрдгрд┐ рдЖрдЦрдбрд▓реЗрд▓реА рдЕрд╕рддреЗ: 42 seconds. рдирдВрддрд░, рдирд╡реАрди рдмреБрдЯрд╛рдВрдд: 12 seconds. "рдирд╡реАрди рдмреВрдЯ 3 рдкрдЯ рдЬрд▓рдж рдЖрд╣реЗрдд!" рдирд╛рд╣реА тАФ рдРрд╢реНрд╡рд░реНрдпрд╛ рдлрдХреНрдд warm up рд╣реЛрдд рд╣реЛрддреА.
рдореНрд╣рдгреВрди рддреНрдпрд╛ рд╣реЗ рдиреАрдЯ рдХрд░рддрд╛рдд:
- рдЖрдзреА рдХрд╛рд╣реА warm-up рдлреЗрд▒реНрдпрд╛, рдЬреНрдпрд╛ рдореЛрдЬрд▓реНрдпрд╛ рдЬрд╛рдд рдирд╛рд╣реАрдд ЁЯФе
- рдордЧ рдПрдХ рдирд╡реНрд╣реЗ, рдЕрдиреЗрдХ heats ЁЯФБ
- рдордЧ рдордзрд▓реА рд╡реЗрд│ (median) рдЖрдгрд┐ рд╡реЗрд│рд╛ рдХрд┐рддреА рдкрд╕рд░рд▓реЗрд▓реНрдпрд╛ рдЖрд╣реЗрдд рддреЗ рдкрд╛рд╣рддрд╛рдд
- рдЬреНрдпрд╛ heat рдордзреНрдпреЗ рдХреБрддреНрд░рд╛ track рд╡рд░ рдзрд╛рд╡рдд рдЖрд▓рд╛ ЁЯРХ рддреА рдПрдХ рд╡рд┐рдЪрд┐рддреНрд░ рд╡реЗрд│ рдЖрд╣реЗ тАФ median рд▓рд╛ рддреНрдпрд╛рдЪреА рдлрд╛рд░рд╢реА рдкрд░реНрд╡рд╛ рдирд╕рддреЗ
рдордЧ рддреНрдпрд╛ рддреБрд▓рдирд╛ рдХрд░рддрд╛рдд. рдЬреБрдиреНрдпрд╛ рдЖрдгрд┐ рдирд╡реНрдпрд╛ рд╡реЗрд│рд╛ рдЦреВрдк overlap рд╣реЛрдд рдЕрд╕рддреАрд▓, рддрд░ рдмреБрдЯрд╛рдВрдиреА рдХреЛрдгрддрд╛рд╣реА рд╕реНрдкрд╖реНрдЯ рдлрд░рдХ рдХреЗрд▓рд╛ рдирд╛рд╣реА. рдирд╡реНрдпрд╛ рд╡реЗрд│рд╛ рд╕реНрдкрд╖реНрдЯрдкрдгреЗ рдХрдореА рдЕрд╕рддреАрд▓ рддрд░рдЪ рддреЛ рдЦрд░рд╛ рдлрд╛рдпрджрд╛ рдЖрд╣реЗ.
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart LR
cold["ЁЯе╢ 3 cold runs<br/>42.1 ┬╖ 31.7 ┬╖ 21.6 ms"] -->|"drop them"| warm["ЁЯФБ 17 warm runs"]
warm --> med["median 12.4 ms<br/>middle half 11.7тАУ12.7"]
b1["B1 tweak: middle half 11.3тАУ12.3"] --> cmp{"do the middle<br/>halves overlap?"}
b2["B2 fix: middle half 7.8тАУ8.4"] --> cmp
med --> cmp
cmp -->|"B1 overlaps"| no["no clear difference"]
cmp -->|"B2 is clear"| yes["B is faster (1.53x)"]
ЁЯЧ║я╕П рдХрд╛рдврд▓реЗрд▓реА рдЖрдХреГрддреА + рдПрдХ lab: https://school-edh.pages.dev/performance/lesson-diagrams.html#l02
тЭУ рдХрд╛рдп
- Benchmark тАФ code рдЪрд╛ рдПрдЦрд╛рджрд╛ рддреБрдХрдбрд╛ (рдХрд┐рдВрд╡рд╛ рд╕рдВрдкреВрд░реНрдг program) рдирд┐рдпрдВрддреНрд░рд┐рдд рдкрд░рд┐рд╕реНрдерд┐рддреАрдд рдЕрдиреЗрдХ рд╡реЗрд│рд╛ рдЪрд╛рд▓рд╡реВрди рдореЛрдЬрдгреЗ. Micro-benchmark рдПрдЦрд╛рджреНрдпрд╛ рдЕрдЧрджреА рдЫреЛрдЯреНрдпрд╛ рдЧреЛрд╖реНрдЯреАрдЪреА рд╡реЗрд│ рдШреЗрддреЛ, рдЬрд╕реЗ рдПрдХ function; macro-benchmark рдПрдЦрд╛рджреНрдпрд╛ рдЦрд▒реНрдпрд╛ task рдЪреА рд╕реБрд░реБрд╡рд╛рддреАрдкрд╛рд╕реВрди рд╢реЗрд╡рдЯрдкрд░реНрдпрдВрдд рд╡реЗрд│ рдШреЗрддреЛ.
- Warm-up тАФ рдкрд╣рд┐рд▓реНрдпрд╛ runs рдирд╛ рдПрдХрджрд╛рдЪ рдпреЗрдгрд╛рд░реЗ рдЦрд░реНрдЪ рднрд░рд╛рд╡реЗ рд▓рд╛рдЧрддрд╛рдд: рдердВрдб CPU caches, operating system рдЪреНрдпрд╛ page cache рдордзреНрдпреЗ рдЕрдЬреВрди рди рдЖрд▓реЗрд▓реНрдпрд╛ files, lazy imports, connection set-up, рдЖрдгрд┐ рдХрд╛рд╣реА runtimes рдордзреНрдпреЗ рдЕрд╕рд╛ JIT compiler рдЬреНрдпрд╛рдиреЗ рдЕрдЬреВрди code optimise рдХреЗрд▓реЗрд▓рд╛ рдирд╛рд╣реА. рддреЗ runs рдЯрд╛рдХреВрди рджреНрдпрд╛ (рдХрд┐рдВрд╡рд╛ users рдирд╛ cold start рджрд┐рд╕рдд рдЕрд╕реЗрд▓ рддрд░ рддреЗ рдореБрджреНрджрд╛рдо рдореЛрдЬрд╛).
- Noise тАФ рдЗрддрд░ programs, CPU frequency рдордзрд▓реЗ рдмрджрд▓ (turbo boost, рдЧрд░рдо laptop рд╣рд│реВ рд╣реЛрдгреЗ), interrupts рдЖрдгрд┐ memory layout рд╣реЗ рд╕рдЧрд│реЗ рдЖрдХрдбреЗ рд╣рд▓рд╡рддрд╛рдд. Simulated рд╕реНрдЯреЙрдкрд╡реЙрдЪ ┬▒8% jitter рдЖрдгрд┐ рдЕрдзреВрдирдордзреВрди рдПрдХ spike рдЬреЛрдбрддреЗ.
- Median рдЖрдгрд┐ рдкрд╕рд╛рд░рд╛ тАФ median рдЖрдгрд┐ рдордзрд▓рд╛ рдЕрд░реНрдзрд╛ рднрд╛рдЧ (p25 рддреЗ p75, рдореНрд╣рдгрдЬреЗ interquartile range) рд╕рд╛рдВрдЧрд╛, рдХрд┐рдВрд╡рд╛ min/median/max. рдХрд╛рд╣реА tools minimum рд╕рд╛рдВрдЧрддрд╛рдд, рдХрд╛рд░рдг noise рдиреЗрд╣рдореА рдлрдХреНрдд рд╡реЗрд│рдЪ рд╡рд╛рдврд╡рддреЛ рдЕрд╕рд╛ рддреНрдпрд╛рдВрдЪрд╛ рдпреБрдХреНрддрд┐рд╡рд╛рдж рдЕрд╕рддреЛ; рд╣реЗ рдЫреЛрдЯреНрдпрд╛, рдлрдХреНрдд-CPU code рд▓рд╛ рд╢реЛрднрддреЗ, рдкрдг рдЦрд░рд╛ рдмрджрд▓ рд▓рдкрд╡рддреЗ.
- рджреЛрди versions рдЪреА рддреБрд▓рдирд╛ тАФ lab рдЪреЗ
verdictрдПрдХ рдЕрдВрджрд╛рдЬреА рдирд┐рдпрдо рд╡рд╛рдкрд░рддреЗ: B рд▓рд╛ рдЬрд▓рдж рдореНрд╣рдгрд╛ рдлрдХреНрдд рддреЗрд╡реНрд╣рд╛ рдЬреЗрд╡реНрд╣рд╛ B рдЪрд╛ p75 рд╣рд╛ A рдЪреНрдпрд╛ p25 рдкреЗрдХреНрд╖рд╛ рдХрдореА рдЕрд╕реЗрд▓ (рдордзрд▓реЗ рдЕрд░реНрдзреЗ рднрд╛рдЧ overlap рд╣реЛрдд рдирд╛рд╣реАрдд). рдЦрд░реА tools statistics рд╡рд╛рдкрд░рддрд╛рдд (рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, pyperf рдЪреЗcompare_toрдлрд░рдХ significant рдЖрд╣реЗ рдХреА рдирд╛рд╣реА рддреЗ рд╕рд╛рдВрдЧрддреЗ). time.perf_counter()тАФ рдПрдХрд╛ machine рд╡рд░ рд╡реЗрд│ рдореЛрдЬрдгреНрдпрд╛рд╕рд╛рдареАрдЪреЗ рдШрдбреНрдпрд╛рд│: monotonic рдЖрдгрд┐ high-resolution.time.time()рдиреЗ code рдЪреА рд╡реЗрд│ рдШреЗрдК рдирдХрд╛ (system clock рджреБрд░реБрд╕реНрдд рдХреЗрд▓реНрдпрд╛рд╡рд░ рддреЗ рдЙрдбреА рдорд╛рд░реВ рд╢рдХрддреЗ).
ЁЯдФ рдХрд╛
рдХрд╛рд░рдг рдкреБрдврдЪрд╛ рдкреНрд░рддреНрдпреЗрдХ рдзрдбрд╛ "рдЬрд▓рдж рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА" code рдмрджрд▓рддреЛ. рдкреНрд░рд╛рдорд╛рдгрд┐рдХ рдореЛрдЬрдорд╛рдкрд╛рд╢рд┐рд╡рд╛рдп рддреБрдореНрд╣реА рдХрд╛рд╣реАрдЪ рди рдХрд░рдгрд╛рд░реЗ рдмрджрд▓ рдареЗрд╡рд╛рд▓, рдорджрдд рдХрд░рдгрд╛рд░реЗ рдмрджрд▓ рдлреЗрдХреВрди рджреНрдпрд╛рд▓, рдЖрдгрд┐ noise рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рдЖрдХрдбреНрдпрд╛рдВрд╡рд░ рд╡рд╛рдж рдШрд╛рд▓рд╛рд▓. рдЬреЛ benchmark 3% рдмрджрд▓ рдкрд╛рд╣реВ рд╢рдХрдд рдирд╛рд╣реА, рддреЛ рддрд╕рд╛ рджрд╛рд╡рд╛ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рд╡рд╛рдкрд░реВ рдирдпреЗ.
ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)
perf/sim.py рдордзрд▓реЗ simulated_runs(base_ms, n, seed) рд╣реЗ рдПрдХ simulated
рд╕реНрдЯреЙрдкрд╡реЙрдЪ рдЖрд╣реЗ: рдкреНрд░рддреНрдпреЗрдХ run рд▓рд╛ base_ms ┬▒ 8% (seeded) рд▓рд╛рдЧрддреЛ, рдкрд╣рд┐рд▓реЗ 3 runs warm-up рдЦрд░реНрдЪ рдЬреЛрдбрддрд╛рдд
(30, 20, 10 ms), рдЖрдгрд┐ 5% runs рдПрдХ spike рдЬреЛрдбрддрд╛рдд. spread(xs) min, p25, median, p75 рдЖрдгрд┐
max рдкрд░рдд рджреЗрддреЗ. verdict(a, b) рд╡рд░рдЪрд╛ рдЕрдВрджрд╛рдЬреА рдирд┐рдпрдо рд▓рд╛рдЧреВ рдХрд░рддреЗ. perf/demo.py рдордзрд▓реЗ
bench() version A (12 ms), рдЫреЛрдЯрд╛ tweak B1 (11.7 ms) рдЖрдгрд┐
рдЦрд░рд╛ fix B2 (8 ms) рдпрд╛рдВрдЪреА рд╡реЗрд│ рдШреЗрддреЗ. рдХрд░реВрди рдкрд╛рд╣рд╛ рдЪреА рд╢реЗрд╡рдЯрдЪреА рдУрд│ Python рдЪреЗ рдЦрд░реЗ timeit рд╡рд╛рдкрд░рддреЗ тАФ рдЦрд░реЗ рдШрдбреНрдпрд╛рд│.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
python3 perf/demo.py bench
python3 - <<'EOF'
import sys; sys.path.insert(0, "perf"); from sim import simulated_runs, spread, verdict
a = simulated_runs(12.0)[3:]
for base in (12.0, 11.5, 11.0, 10.5, 10.0, 9.0):
b = simulated_runs(base, seed=6)[3:]
print(f"B at {base:>4} ms тЖТ median {spread(b)['median']:>4} ┬╖ {verdict(a, b)}")
for n in (3, 5, 10, 20):
print(f"{n:>2} runs, warm-up kept тЖТ median {spread(simulated_runs(12.0, n=n))['median']:>4} ms")
EOF
python3 -m timeit -n 1000 -r 5 "sorted(range(1000, 0, -1))"
рд╢реЗрд╡рдЯрдЪрд╛ command рддреБрдордЪреНрдпрд╛ machine рд╡рд░ рдЦрд▒реНрдпрд╛ sort рдЪреА рд╡реЗрд│ рдШреЗрддреЛ тАФ рдХрд╛рд╣реАрд╕реЗ рдЕрд╕реЗ:
1000 loops, best of 5: 5.62 usec per loop. рддреБрдордЪреЗ рдЖрдХрдбреЗ рд╡реЗрдЧрд│реЗ рдЕрд╕рддреАрд▓, рдкреНрд░рддреНрдпреЗрдХ run рд▓рд╛ рдЖрдгрд┐
рдкреНрд░рддреНрдпреЗрдХ machine рд╡рд░; рд╣рд╛рдЪ рддрд░ рдпрд╛ рдзрдбреНрдпрд╛рдЪрд╛ рдореБрджреНрджрд╛ рдЖрд╣реЗ.
тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ
bench рд╣реЗ рдЫрд╛рдкрддреЗ:
тФАтФА Katrina times version A 20 times (simulated stopwatch): first three runs [42.1, 31.7, 21.6] ms тАФ cold, warming up
one run says 42.1 ms ┬╖ the mean of all 20 says 15.5 ms ┬╖ after 3 warm-up runs, the median of 17 says 12.4 ms
spread of the 17: min 11.2 ┬╖ p25 11.7 ┬╖ median 12.4 ┬╖ p75 12.7 ┬╖ max 19.9 (one spike: another program woke up)
тФАтФА A vs B1 (a small tweak): medians 12.4 vs 12.0 ms ┬╖ middle halves 11.7тАУ12.7 vs 11.3тАУ12.3 тЖТ no clear difference: the change is smaller than the noise
тФАтФА A vs B2 (a real fix): medians 12.4 vs 8.1 ms ┬╖ middle halves 11.7тАУ12.7 vs 7.8тАУ8.4 тЖТ B is faster (1.53x)
рддреБрдордЪрд╛ snippet рд╣реЗ рдЫрд╛рдкрддреЛ:
B at 12.0 ms тЖТ median 12.3 ┬╖ no clear difference: the change is smaller than the noise
B at 11.5 ms тЖТ median 11.8 ┬╖ no clear difference: the change is smaller than the noise
B at 11.0 ms тЖТ median 11.3 ┬╖ B is faster (1.10x)
B at 10.5 ms тЖТ median 10.8 ┬╖ B is faster (1.15x)
B at 10.0 ms тЖТ median 10.2 ┬╖ B is faster (1.22x)
B at 9.0 ms тЖТ median 9.2 ┬╖ B is faster (1.35x)
3 runs, warm-up kept тЖТ median 31.7 ms
5 runs, warm-up kept тЖТ median 21.6 ms
10 runs, warm-up kept тЖТ median 12.9 ms
20 runs, warm-up kept тЖТ median 12.6 ms
ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ
рдПрдХрд╛ рдердВрдб run рдиреЗ 42.1 ms рд╕рд╛рдВрдЧрд┐рддрд▓реЗ; рдкреНрд░рд╛рдорд╛рдгрд┐рдХ рдЙрддреНрддрд░ 12.4 ms рдЖрд╣реЗ тАФ 3 рдкрдЯреАрдкреЗрдХреНрд╖рд╛ рдЬрд╛рд╕реНрдд рдХрдореА. рд╕рдЧрд│реНрдпрд╛ 20 рдЪрд╛ mean (15.5) warm-up рдЖрдгрд┐ spike рдореБрд│реЗ рдЕрдЬреВрдирд╣реА рд╡рд░ рдУрдврд▓рд╛ рдЧреЗрд▓рд╛ рд╣реЛрддрд╛. рдЗрддрдХреНрдпрд╛ noise рдордзреНрдпреЗ, рд╕реБрдорд╛рд░реЗ 4% рдЪрд╛ рдмрджрд▓ (12.0 тЖТ 11.5) рджрд┐рд╕рддрдЪ рдирд╛рд╣реА; рд╕реБрдорд╛рд░реЗ 8% (тЖТ 11.0) рд╣рд╛ рдпрд╛рдкреИрдХреА рддреЛ рдкрд╛рд╣реВ рд╢рдХрдгрд╛рд░рд╛ рд╕рд░реНрд╡рд╛рдд рд▓рд╣рд╛рди рдЯрдкреНрдкрд╛ рдЖрд╣реЗ. рдЖрдгрд┐ рдлрдХреНрдд 3 рдХрд┐рдВрд╡рд╛ 5 runs рдЖрдгрд┐ warm-up рди рдХрд╛рдврддрд╛, median рд╕реНрд╡рддрдГрдЪ рдЪреБрдХреАрдЪрд╛ рдпреЗрддреЛ. рдЬрд╛рд╕реНрдд runs рдЖрдгрд┐ warm-up benchmark рдЕрдзрд┐рдХ рдзрд╛рд░рджрд╛рд░ рдХрд░рддрд╛рдд.
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
- рдПрдХрд╛ run рдЪреА, рдХрд┐рдВрд╡рд╛ рдкрд╣рд┐рд▓реНрдпрд╛ run рдЪреА рд╡реЗрд│ рдШреЗрдКрди рддреЗрдЪ рдЙрддреНрддрд░ рдореНрд╣рдгрдгреЗ
- рд╡реЗрдЧрд╡реЗрдЧрд│реНрдпрд╛ machines, рджрд┐рд╡рд╕ рдХрд┐рдВрд╡рд╛ power settings рд╡рд░рдЪреНрдпрд╛ рджреЛрди рдЖрдХрдбреНрдпрд╛рдВрдЪреА рддреБрд▓рдирд╛ рдХрд░рдгреЗ
- рдЕрд╕рд╛ benchmark рдЬреЛ compiler рдХрд┐рдВрд╡рд╛ runtime рд╡рдЧрд│реВ рд╢рдХрддреЛ (result рдХрдзреАрдЪ рд╡рд╛рдкрд░рд▓рд╛ рдЬрд╛рдд рдирд╛рд╣реА)
- рдЦрд▒реНрдпрд╛ рд╡реЗрд│реЗрдЪреНрдпрд╛ рдлрдХреНрдд 1% рдЕрд╕рд▓реЗрд▓реНрдпрд╛ function рдЪрд╛ micro-benchmark рдХрд░рдгреЗ (рдЖрдзреА profile рдХрд░рд╛ тАФ рдзрдбрд╛ 03)
- рд╡реЗрд│ рдореЛрдЬрддрд╛рдирд╛
timeitgarbage collector рдмрдВрдж рдХрд░рддреЗ тАФ рднрд░рдкреВрд░ garbage рдмрдирд╡рдгрд╛рд░рд╛ code рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рдЕрд╕реЗрд▓ рддреНрдпрд╛рдкреЗрдХреНрд╖рд╛ рдЬрд▓рдж рджрд┐рд╕рддреЛ - рдЬреНрдпрд╛рдЪреЗ runs 8% рдиреЗ рдмрджрд▓рддрд╛рдд рдЕрд╢рд╛ benchmark рд╡рд░реВрди "2% рдЬрд▓рдж" рдЕрд╕рд╛ рджрд╛рд╡рд╛ рдХрд░рдгреЗ
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд
рдЦрд▒реНрдпрд╛ machine рд╡рд░ тАФ pyperf рдкреНрд░рддреНрдпреЗрдХ benchmark рдЕрдиреЗрдХ рдирд╡реНрдпрд╛ processes рдордзреНрдпреЗ рдЪрд╛рд▓рд╡рддреЛ, loop count
calibrate рдХрд░рддреЛ, warm-ups рдХрд╛рдвреВрди рдЯрд╛рдХрддреЛ рдЖрдгрд┐ mean ┬▒ standard deviation рд╕рд╛рдВрдЧрддреЛ:
python3 -m pip install pyperf
python3 -m pyperf timeit -o old.json -s "data = list(range(1000, 0, -1))" "sorted(data)"
# change the code, then:
python3 -m pyperf timeit -o new.json -s "data = list(range(1000, 0, -1))" "sorted(data)"
python3 -m pyperf compare_to old.json new.json # says if the difference is significant
python3 -m pyperf system tune # (Linux, root) quieter CPU settings for benchmarking
hyperfine рд╕рдВрдкреВрд░реНрдг commands рд╕рд╛рдареА рд╣реЗрдЪ рдХрд░рддреЛ, warm-up runs рд╕рд╣:
hyperfine --warmup 3 --runs 20 'python3 old_report.py' 'python3 new_report.py'
рддреБрдордЪреНрдпрд╛ рд╕реНрд╡рддрдГрдЪреНрдпрд╛ code рдордзреНрдпреЗ, monotonic рдШрдбреНрдпрд╛рд│ рд╡рд╛рдкрд░рд╛:
import time
t0 = time.perf_counter()
build_results()
print(f"{(time.perf_counter() - t0) * 1000:.1f} ms")
ЁЯПн Production рдордзреНрдпреЗ рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ рдЖрд╣реЗ: benchmark results рддреЗ рдмрдирд╡рдгрд╛рд▒реНрдпрд╛ commit рд╕реЛрдмрдд рдареЗрд╡рд╛, рддреЗ рддреНрдпрд╛рдЪ рд╢рд╛рдВрдд machine рд╡рд░ рдЪрд╛рд▓рд╡рд╛, рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ рдЖрдХрдбреНрдпрд╛рд╢реЗрдЬрд╛рд░реА рдкрд╕рд╛рд░рд╛ рд▓рд┐рд╣рд╛. рдкрд╕рд╛рд▒реНрдпрд╛рдкреЗрдХреНрд╖рд╛ рд▓рд╣рд╛рди speed-up рд╣рд╛ result рдирд╛рд╣реА.
тПня╕П рдкреБрдвреЗ
рдЖрддрд╛ рддреБрдореНрд╣реА рдПрдЦрд╛рджрд╛ program рдореЛрдЬреВ рд╢рдХрддрд╛. рдкрдг рддреНрдпрд╛рдЪрд╛ рдХреЛрдгрддрд╛ рднрд╛рдЧ рд╣рд│реВ рдЖрд╣реЗ? рдкреБрдвреЗ: рдкреНрд░рд╢рд┐рдХреНрд╖рд┐рдХреЗрдЪрд╛ clipboard тАФ profiling.
git checkout lesson-03-profiling