ЁЯОТ рдзрдбрд╛ 05 тАФ Memory: рд╕рдЧрд│реЗ рдЕрдбрдерд│реЗ рдПрдХрджрдо, рдХреА рдПрдХрд╛ рд╡реЗрд│реА рдПрдХ?
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 05 ┬╖ рдорд╛рдЧреЗ: lesson-04-complexity ┬╖ рдкреБрдвреЗ: lesson-06-caching
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбреЗ 01тАУ04, рдЕрдзрд┐рдХ memory: program рдПрдХрд╛ рд╡реЗрд│реА рдХрд┐рддреА рдзрд░реВрди рдареЗрд╡рддреЛ, рддреЗ
tracemalloc рдиреЗ рдХрд╕реЗ рдореЛрдЬрд╛рдпрдЪреЗ, рдЖрдгрд┐ Python рдордзрд▓рд╛ рд╕рд░реНрд╡рд╛рдд рд╕реЛрдкрд╛ рдореЛрдард╛ рдЙрдкрд╛рдп тАФ рд╕рдЧрд│реЗ items рдзрд░реВрди рдареЗрд╡рдгрд╛рд▒реНрдпрд╛ list рдРрд╡рдЬреА
рдПрдХрд╛ рд╡реЗрд│реА рдПрдХ item рдмрдирд╡рдгрд╛рд░рд╛ generator. perf/demo.py рдордзрд▓реЗ memory() рдЖрдгрд┐
perf/sim.py рдордзрд▓реЗ total_list, total_gen, peak_kb рдЖрдгрд┐
held_at_once.
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
рдЕрдбрдерд│реНрдпрд╛рдВрдЪреНрдпрд╛ рд╢рд░реНрдпрддреАрд▓рд╛ 100,000 рдЕрдбрдерд│реЗ рд▓рд╛рдЧрддрд╛рдд (рдЦреВрдкрдЪ рд▓рд╛рдВрдм рд╢рд░реНрдпрдд ЁЯШД). рддреЗ рд╕рд╛рд╣рд┐рддреНрдпрд╛рдЪреНрдпрд╛ рдЦреЛрд▓реАрдд рдареЗрд╡рд▓реЗрд▓реЗ рдЕрд╕рддрд╛рдд. ЁЯПЪя╕П
- рдкрджреНрдзрдд 1 тАФ рдЖрдзреА рд╕рдЧрд│реЗ рдмрд╛рд╣реЗрд░ рдЖрдгрд╛. рдкреНрд░рддреНрдпреЗрдХ рдЕрдбрдерд│рд╛ рдореИрджрд╛рдирд╛рд╡рд░ рд░рдЪрд╛, рдордЧ рддреЗ рдПрдХреЗрдХ рдХрд░реВрди рд╡рд╛рдкрд░рд╛. рдореИрджрд╛рди рдЕрдбрдерд│реНрдпрд╛рдВрдиреА рднрд░реВрди рдЬрд╛рддреЗ. рджреБрд╕рд▒реНрдпрд╛ рдХрд╢рд╛рд▓рд╛рдЪ рдЬрд╛рдЧрд╛ рдЙрд░рдд рдирд╛рд╣реА.
- рдкрджреНрдзрдд 2 тАФ рдПрдХрд╛ рд╡реЗрд│реА рдПрдХ. рдРрд╢реНрд╡рд░реНрдпрд╛ рдПрдХ рдЕрдбрдерд│рд╛ рдЖрдгрддреЗ, рдзрд╛рд╡рдкрдЯреВ рддреНрдпрд╛рд╡рд░реВрди рдЙрдбреА рдорд╛рд░рддреЛ, рддреА рддреЛ рдкрд░рдд рдиреЗрддреЗ рдЖрдгрд┐ рдкреБрдврдЪрд╛ рдЖрдгрддреЗ. рдореИрджрд╛рдирд╛рд╡рд░ рдХрдзреАрд╣реА рдПрдХрдЪ рдЕрдбрдерд│рд╛ рдЕрд╕рддреЛ.
рд╢рд░реНрдпрдд рддреАрдЪ. рдЙрддреНрддрд░ рддреЗрдЪ. рдкрдг рдкрджреНрдзрдд 2 рд▓рд╛ рдЬрд╡рд│рдЬрд╡рд│ рдЬрд╛рдЧрд╛рдЪ рд▓рд╛рдЧрдд рдирд╛рд╣реА.
рдпрд╛рдд рдПрдХ рдЕрдбрдЪрдг рдЖрд╣реЗ. рдкрджреНрдзрдд 2 рдордзреНрдпреЗ, рдПрдХрджрд╛ рдЕрдбрдерд│рд╛ рдЦреЛрд▓реАрдд рдкрд░рдд рдЧреЗрд▓рд╛ рдХреА рддреЛ рдореИрджрд╛рдирд╛рд╡рд░реВрди рдЧреЗрд▓рд╛рдЪ. рддреБрдореНрд╣рд╛рд▓рд╛ рд╕рдЧрд│реЗ рдЕрдбрдерд│реЗ рдкреБрдиреНрд╣рд╛ рдкрд╛рд╣рд╛рдпрдЪреЗ рдЕрд╕рддреАрд▓, рдХрд┐рдВрд╡рд╛ рдореЛрдЬрд╛рдпрдЪреЗ рдЕрд╕рддреАрд▓, рдХрд┐рдВрд╡рд╛ рд╡реЗрдЧрд│реНрдпрд╛ рдХреНрд░рдорд╛рдиреЗ рддреНрдпрд╛рд╡рд░реВрди рдЙрдбреНрдпрд╛ рдорд╛рд░рд╛рдпрдЪреНрдпрд╛ рдЕрд╕рддреАрд▓, рддрд░ рддреБрдореНрд╣рд╛рд▓рд╛ рдкрджреНрдзрдд 1 рд▓рд╛рдЧрддреЗ.
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart LR
src["range(100,000)"] --> lst["ЁЯУж list: [i*i for i in ...]<br/>holds 100,000 results at once"]
src --> gen["ЁЯФБ generator: (i*i for i in ...)<br/>holds 1 result at a time"]
lst --> sum1["sum тЖТ 333,328,333,350,000"]
gen --> sum2["sum тЖТ 333,328,333,350,000"]
lst --> peak["tracemalloc peak:<br/>list > 100├Ч generator"]
ЁЯЧ║я╕П рдХрд╛рдврд▓реЗрд▓реА рдЖрдХреГрддреА + рдПрдХ lab: https://school-edh.pages.dev/performance/lesson-diagrams.html#l05
тЭУ рдХрд╛рдп
- Allocation тАФ рдирд╡реАрди object рдареЗрд╡рдгреНрдпрд╛рд╕рд╛рдареА memory рдорд╛рдЧрдгреЗ. Python рдордзреНрдпреЗ рдЬрд╡рд│рдЬрд╡рд│ рдкреНрд░рддреНрдпреЗрдХ рдЧреЛрд╖реНрдЯ
object рдЖрд╣реЗ: рдкреНрд░рддреНрдпреЗрдХ
int, рдкреНрд░рддреНрдпреЗрдХstr, рдкреНрд░рддреНрдпреЗрдХ list. 100,000 рд╕рдВрдЦреНрдпрд╛рдВрдЪреА list рдореНрд╣рдгрдЬреЗ 100,000 references рдзрд░рдгрд╛рд░рд╛ рдПрдХ list object, рдЕрдзрд┐рдХ рд╕реНрд╡рддрдГ рддреЗ 100,000 number objects (тИТ5 рддреЗ 256 рдкрд░реНрдпрдВрддрдЪреЗ рдЫреЛрдЯреЗ ints share рд╣реЛрддрд╛рдд; рдмрд╛рдХреА рдмрд╣реБрддреЗрдХ рд╕реНрд╡рддрдВрддреНрд░ objects рдЕрд╕рддрд╛рдд). - Peak memory тАФ program рдиреЗ рдХреЛрдгрддреНрдпрд╛рд╣реА рдПрдХрд╛ рдХреНрд╖рдгреА рдзрд░рд▓реЗрд▓реА рд╕рд░реНрд╡рд╛рдд рдЬрд╛рд╕реНрдд memory. Job рддреНрдпрд╛рдЪреНрдпрд╛ container рдордзреНрдпреЗ рдорд╛рд╡рддреЛ рдХреА memory рд╕рдВрдкрд▓реНрдпрд╛рдореБрд│реЗ рдорд╛рд░рд▓рд╛ рдЬрд╛рддреЛ (OOM killer), рд╣реЗ рддреАрдЪ рдард░рд╡рддреЗ.
tracemallocтАФ Python рдиреЗ allocate рдХреЗрд▓реЗрд▓реНрдпрд╛ memory blocks рдЪрд╛ рдорд╛рдЧ рдареЗрд╡рдгрд╛рд░реЗ standard-library module.get_traced_memory()bytes рдордзреНрдпреЗ(current, peak)рдкрд░рдд рджреЗрддреЗ. рддреЗ рдлрдХреНрдд Python рдЪреНрдпрд╛ allocations рдкрд╛рд╣рддреЗ: рдХрд╛рд╣реА C libraries рдереЗрдЯ рдШреЗрддрд▓реЗрд▓реА memory рдореЛрдЬрд▓реА рдЬрд╛рдд рдирд╛рд╣реА. рдЕрдЪреВрдХ рдЖрдХрдбреЗ Python version рдЖрдгрд┐ platform рдиреБрд╕рд╛рд░ рдмрджрд▓рддрд╛рдд.- RSS (resident set size) тАФ operating system рдиреБрд╕рд╛рд░ рд╕рдВрдкреВрд░реНрдг process рдХрд┐рддреА memory
рд╡рд╛рдкрд░рддреЛ рддреЗ. рддреНрдпрд╛рдд interpreter рдЖрдгрд┐ libraries рдпреЗрддрд╛рдд, рдЖрдгрд┐ Python рдореЛрдХрд│реА рдХреЗрд▓реЗрд▓реА memory
system рд▓рд╛ рдиреЗрд╣рдореА рд▓рдЧреЗрдЪ рдкрд░рдд рджреЗрдд рдирд╛рд╣реА.
tracemallocpeak рдЖрдгрд┐ RSS рд╡реЗрдЧрд╡реЗрдЧрд│реНрдпрд╛ рдкреНрд░рд╢реНрдирд╛рдВрдЪреА рдЙрддреНрддрд░реЗ рджреЗрддрд╛рдд. - List тАФ рдкреНрд░рддреНрдпреЗрдХ element рдЖрддреНрддрд╛рдЪ рдмрдирд╡рддреЗ; рддреБрдореНрд╣реА рддреНрдпрд╛рд╡рд░ рдкреБрдиреНрд╣рд╛ loop рдХрд░реВ рд╢рдХрддрд╛, index рдХрд░реВ рд╢рдХрддрд╛, рддреНрдпрд╛рдЪрд╛
len()рдШреЗрдК рд╢рдХрддрд╛. Generator тАФ рдЕрд╢реА рдХреГрддреА рдЬреА рдкреБрдврдЪрд╛ element рдлрдХреНрдд рдорд╛рдЧрд┐рддрд▓реНрдпрд╛рд╡рд░рдЪ рдмрдирд╡рддреЗ. рддреА рдПрдХрд╛ рд╡реЗрд│реА рдПрдХрдЪ рдзрд░рддреЗ, рдЖрдгрд┐ рддреА рдлрдХреНрдд рдПрдХрджрд╛рдЪ рдЪрд╛рд│рддрд╛ рдпреЗрддреЗ. - Memory рдореБрд│реЗ рд╡реЗрд│рд╣реА рдХрд╛ рдЦрд░реНрдЪ рд╣реЛрддреЛ тАФ рдкреНрд░рддреНрдпреЗрдХ allocation рд╣реЗ рдХрд╛рдо рдЖрд╣реЗ, рдореЛрдард╛ heap рдореНрд╣рдгрдЬреЗ garbage collector рд▓рд╛ рдкрд╛рд╣рд╛рдпрд▓рд╛ рдЬрд╛рд╕реНрдд, CPU caches рдордзреНрдпреЗ рди рдорд╛рд╡рдгрд╛рд░рд╛ data рд╡рд╛рдЪрд╛рдпрд▓рд╛ рд╣рд│реВ рдЕрд╕рддреЛ, рдЖрдгрд┐ RAM рд╕рдВрдкрд▓реЗрд▓реЗ machine disk рд╡рд░ swapping рд╕реБрд░реВ рдХрд░рддреЗ.
ЁЯдФ рдХрд╛
рдХрд╛рд░рдг "test file рд╕рд╣ рдорд╛рдЭреНрдпрд╛ laptop рд╡рд░ рдЪрд╛рд▓рд▓реЗ" рдЖрдгрд┐ "рдЦрд▒реНрдпрд╛ file рд╕рд╣ production рдордзреНрдпреЗ рдорд╛рд░рд▓реЗ рдЧреЗрд▓реЗ" рд╣реЗ рд╡реЗрдЧрд╡реЗрдЧрд│реНрдпрд╛ data рдЖрдХрд╛рд░рд╛рдВрдЪреЗ рдПрдХрдЪ program рдЖрд╣реЗ. рд╕рдВрдкреВрд░реНрдг 10 GB log list рдордзреНрдпреЗ рд╡рд╛рдЪрдгрд╛рд▒реНрдпрд╛ report рд▓рд╛ 10 GB рдЖрдгрд┐ рддреНрдпрд╛рд╣реВрди рдЬрд╛рд╕реНрдд рд▓рд╛рдЧрддрд╛рдд; рддреЛрдЪ report рдУрд│-рдУрд│ рд╡рд╛рдЪрддрд╛рдирд╛ рдХрд╛рд╣реА kilobytes рд▓рд╛рдЧрддрд╛рдд. рддреБрдореНрд╣реА рдПрдХрд╛ рд╡реЗрд│реА рдХрд╛рдп рдзрд░рддрд╛ рд╣реЗ рдорд╛рд╣реАрдд рдЕрд╕рдгреЗ, рд╣рд╛рдЪ рдмрд▒реНрдпрд╛рдЪрджрд╛ рдЪрд╛рд▓рдгрд╛рд▒реНрдпрд╛ job рдЖрдгрд┐ crash рд╣реЛрдгрд╛рд▒реНрдпрд╛ job рдордзрд▓рд╛ рдлрд░рдХ рдЕрд╕рддреЛ.
ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)
perf/sim.py рдордзрд▓реЗ total_list(n) [i * i for i in range(n)] рдЪреА рдмреЗрд░реАрдЬ рдХрд░рддреЗ тАФ рдПрдХ
list; total_gen(n) (i * i for i in range(n)) рдЪреА рдмреЗрд░реАрдЬ рдХрд░рддреЗ тАФ рдПрдХ generator. peak_kb(fn, n)
tracemalloc рд╕реБрд░реВ рдХрд░рддреЗ, function рдЪрд╛рд▓рд╡рддреЗ, peak рд╡рд╛рдЪрддреЗ рдЖрдгрд┐ tracing рдерд╛рдВрдмрд╡рддреЗ. held_at_once рд╣рд╛
count model рдЖрд╣реЗ: list рд╕рд╛рдареА n, generator рд╕рд╛рдареА 1. Demo рддреБрд▓рдирд╛ рд╣реЛ/рдирд╛рд╣реА рдореНрд╣рдгреВрди рдЫрд╛рдкрддреЛ,
рдХрд╛рд░рдг рдЕрдЪреВрдХ bytes рддреБрдордЪреНрдпрд╛ Python version рд╡рд░ рдЕрд╡рд▓рдВрдмреВрди рдЕрд╕рддрд╛рдд.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
python3 perf/demo.py memory
python3 - <<'EOF'
import sys; sys.path.insert(0, "perf"); from sim import total_list, total_gen, peak_kb
g = (i * i for i in range(5))
print("a generator runs once:", sum(g), "then", sum(g))
squares = [i * i for i in range(5)]
print("a list can be reused:", sum(squares), "then", sum(squares), "┬╖ length", len(squares), "┬╖ last", squares[-1])
for n in (10_000, 100_000, 1_000_000):
lk, gk = peak_kb(total_list, n), peak_kb(total_gen, n)
print(f"n {n:>9,}: list peak {lk / 1024:6.1f} MB ┬╖ generator peak {gk:5.1f} KB (exact bytes vary by Python version)")
EOF
рд╢реЗрд╡рдЯрдЪреНрдпрд╛ рддреАрди рдУрд│реА рдЦрд░реА tracemalloc рдореЛрдЬрдорд╛рдкреЗ рдЖрд╣реЗрдд тАФ Mac рд╡рд░ Python 3.9 рд╡рд░ рддреА
list рд╕рд╛рдареА рд╕реБрдорд╛рд░реЗ 0.3 MB, 3.7 MB рдЖрдгрд┐ 38.4 MB рдЖрдгрд┐ generator рд╕рд╛рдареА рд╕реБрдорд╛рд░реЗ 0.3 KB рд╣реЛрддреА.
рддреБрдордЪреЗ рдЖрдХрдбреЗ рдереЛрдбреЗ рд╡реЗрдЧрд│реЗ рдЕрд╕рддреАрд▓; рдирдореБрдирд╛ (list n рд╕реЛрдмрдд рд╡рд╛рдврддреЗ, generator
рд╡рд╛рдврдд рдирд╛рд╣реА) рдмрджрд▓рдгрд╛рд░ рдирд╛рд╣реА.
тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ
memory рд╣реЗ рдЫрд╛рдкрддреЗ:
тФАтФА the sum of squares of 0..99,999: a list holds every result, a generator makes one at a time
same answer: True (333,328,333,350,000)
results held at once: list 100,000 ┬╖ generator 1
tracemalloc peak: the list needs over 100├Ч the generator's memory: True
рддреБрдордЪрд╛ snippet рдпрд╛рдиреЗ рд╕реБрд░реВ рд╣реЛрддреЛ:
a generator runs once: 30 then 0
a list can be reused: 30 then 30 ┬╖ length 5 ┬╖ last 16
ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ
рдЙрддреНрддрд░ рддреЗрдЪ, рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ рд╡реЗрд│реА n рджрд╣рд╛ рдкрдЯ рд╡рд╛рдврд▓реНрдпрд╛рд╡рд░ list рдЪреА peak memory рджрд╣рд╛ рдкрдЯ рд╡рд╛рдврд▓реА, рддрд░
generator рдЪреА рд╕рдкрд╛рдЯ рд░рд╛рд╣рд┐рд▓реА тАФ рддреНрдпрд╛рдиреЗ рдХрдзреАрд╣реА рдПрдХрдЪ рд╡рд░реНрдЧ рдзрд░рд▓рд╛. рдкрдг generator рдЪрд╛ рджреБрд╕рд░рд╛
sum 0 рдЖрд▓рд╛: рддреЛ рд╕рдВрдкреВрди рдЧреЗрд▓рд╛ рд╣реЛрддрд╛. рдореНрд╣рдгреВрди рдирд┐рдпрдо "generators рдЪрд╛рдВрдЧрд▓реЗ рдЕрд╕рддрд╛рдд" рдЕрд╕рд╛ рдирд╛рд╣реА; рддреЛ рдЕрд╕рд╛ рдЖрд╣реЗ:
"рдЬреЗ рдлрдХреНрдд рдПрдХрджрд╛рдЪ рдЪрд╛рд│рд╛рдпрдЪреЗ рдЖрд╣реЗ рддреЗ рдзрд░реВрди рдареЗрд╡реВ рдирдХрд╛".
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
- рдЕрдЬреНрдЮрд╛рдд рдЖрдХрд╛рд░рд╛рдЪреНрдпрд╛ file рд╡рд░
f.read()рдХрд┐рдВрд╡рд╛f.readlines()тАФ рддреНрдпрд╛рдРрд╡рдЬреАfрд╡рд░ рдУрд│-рдУрд│ loop рдХрд░рд╛ - "рд╕реБрд░рдХреНрд╖рд┐рддрддреЗрд╕рд╛рдареА" generator рднреЛрд╡рддреА
list(...), рдЬреНрдпрд╛рдореБрд│реЗ рд╕рдВрдкреВрд░реНрдг рдЦрд░реНрдЪ рдкрд░рдд рдпреЗрддреЛ - generator рджреЛрдирджрд╛ рдЪрд╛рд│рдгреЗ рдЖрдгрд┐ рджреБрд╕рд▒реНрдпрд╛ рд╡реЗрд│реА рдХрд╛рд╣реАрдЪ рди рдорд┐рд│рдгреЗ
- рдЪреБрдХреВрди рдореЛрдареЗ objects рдЬрд┐рд╡рдВрдд рдареЗрд╡рдгреЗ тАФ рдорд░реНрдпрд╛рджрд╛ рдирд╕рд▓реЗрд▓рд╛ cache (рдзрдбрд╛ 06), global list, reference рдареЗрд╡рдгрд╛рд░рд╛ closure
- RSS рдПрдХрджрд╛ рд╡рд╛рдЪреВрди рддреЛ leak рдЖрд╣реЗ рдЕрд╕реЗ рд╕рдордЬрдгреЗ; рд╕реНрдерд┐рд░ load рдЦрд╛рд▓реА, рд╡реЗрд│реЗрдиреБрд╕рд╛рд░ рддреНрдпрд╛рд╡рд░ рд▓рдХреНрд╖ рдареЗрд╡рд╛
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд
рдЦрд▒реНрдпрд╛ machine рд╡рд░ тАФ рджреЛрди snapshots рд╡рд╛рдкрд░реВрди рдХреЛрдгрддреНрдпрд╛ рдУрд│реА рд╕рд░реНрд╡рд╛рдд рдЬрд╛рд╕реНрдд allocate рдХрд░рддрд╛рдд рддреЗ рд╢реЛрдзрд╛:
import tracemalloc
tracemalloc.start()
before = tracemalloc.take_snapshot()
build_results()
after = tracemalloc.take_snapshot()
for stat in after.compare_to(before, "lineno")[:5]:
print(stat) # file:line, size and count difference
рдореЛрдареНрдпрд╛ files рдЖрдгрд┐ query results load рдХрд░рдгреНрдпрд╛рдРрд╡рдЬреА stream рдХрд░рд╛:
with open("laps.csv") as f: # one line at a time
best = min(int(line.split(",")[2]) for line in f)
for row in cursor: # a DB cursor also streams (fetchmany under the hood)
handle(row)
memray (Linux рдЖрдгрд┐ macOS) рдкреНрд░рддреНрдпреЗрдХ allocation рдиреЛрдВрджрд╡рддреЛ, native рд╕реБрджреНрдзрд╛, рдЖрдгрд┐
flame graph рдХрд╛рдврддреЛ:
python3 -m pip install memray
python3 -m memray run -o results.bin make_results.py
python3 -m memray flamegraph results.bin
рдПрдХрд╛рдЪ class рдЪреНрдпрд╛ рдЕрдиреЗрдХ рдЫреЛрдЯреНрдпрд╛ objects рд╕рд╛рдареА, __slots__ рдкреНрд░рддреНрдпреЗрдХ instance рдЪрд╛ __dict__ рдХрд╛рдвреВрди рдЯрд╛рдХрддреЛ рдЖрдгрд┐
memory рд╡рд╛рдЪрд╡рддреЛ:
class Lap:
__slots__ = ("runner_id", "lap_ms")
def __init__(self, runner_id, lap_ms): self.runner_id, self.lap_ms = runner_id, lap_ms
ЁЯПн Production рдордзреНрдпреЗ рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ рдЖрд╣реЗ: рдкреНрд░рддреНрдпреЗрдХ container рд╡рд░ memory limit рдареЗрд╡рд╛ рдЖрдгрд┐ input рдЪреНрдпрд╛ рдЖрдХрд╛рд░рд╛рд╢реЗрдЬрд╛рд░реА memory chart рдХрд░рд╛. Data рд╕реЛрдмрдд memory рд╡рд╛рдврдд рдЕрд╕реЗрд▓, рддрд░ stream рдЕрд╕рд╛рдпрд▓рд╛ рд╣рд╡реА рд╣реЛрддреА рддреА list рд╢реЛрдзрд╛.
тПня╕П рдкреБрдвреЗ
рдХрдзреА рдХрдзреА рд╕рд░реНрд╡рд╛рдд рдЬрд▓рдж рдХрд╛рдо рдореНрд╣рдгрдЬреЗ рдЬреЗ рддреБрдореНрд╣реА рдкреБрдиреНрд╣рд╛ рдХрд░рдд рдирд╛рд╣реА рддреЗ. рдкреБрдвреЗ: рд▓рдХреНрд╖рд╛рдд рдареЗрд╡рдгрд╛рд░рд╛ scoreboard тАФ caching рдЖрдгрд┐ memoization, рдЖрдгрд┐ hit ratio.
git checkout lesson-06-caching