perf(B09 [저장] · 708-1): 같은 입력 되풀이 셈 묶음 — 화면 [저장] 3.7 s → 1.7 s · 결과 바이트 같음
- M01 캐시 `steady()` 범위 — 요청 한 번 안 파일 자국 한 번(77 번 × 19 ms → 1 번) · stale · forget 뒤 다시 · 범위 밖 그대로 - 두 번 셈(183-1) 2차 산근 = 1차가 본 단가(있음 · 값)가 같을 때만 1차 풀이 사본 · 다르면 다시 셈 - [저장] 단가 수요 한 번(셈 답에 넘김) · 단계 표시 = 셈과 함께 - B08 `once()` 범위 — B09 원천 읽기 때 토공 채집석 공제가 자재 집계표 답을 다시 씀(두 번 셈 → 한 번) - 시험: test_b09_save_speed 새로 · test_183 바꿔 끼운 셈 함수 = 새 memo 인자 받음 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,8 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import contextvars
|
||||
import json
|
||||
import sys
|
||||
import threading
|
||||
@@ -28,6 +30,28 @@ _INDEX: dict = {} # 폴더 · 자국 · files · whole
|
||||
_BLOCK: dict[str, tuple[tuple, dict]] = {} # 로직 파일 → (자국, {키: `_check` 가 센 것})
|
||||
_BASE: dict[str, tuple] = {} # 막힘을 셀 때 바탕이던, 로직 아닌 파일의 자국
|
||||
_MARKED: dict[str, set] = {} # 우리가 고친 요소·표 파일 → 흔들린 자리(`narrow` 가 고른 것)
|
||||
#: `steady()` 범위 — 폴더 → 자국(범위 안에선 자국 한 번 · `to_thread` 도 같은 묶음)
|
||||
_STEADY: contextvars.ContextVar[dict | None] = contextvars.ContextVar("m01_steady", default=None)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def steady():
|
||||
"""요청 한 번처럼 마스터가 안 바뀌는 범위 — `loaded` 가 파일 자국을 한 번만 셈."""
|
||||
token = _STEADY.set({}) if _STEADY.get() is None else None
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
if token is not None:
|
||||
_STEADY.reset(token)
|
||||
|
||||
|
||||
def _now(folder: Path) -> dict[str, tuple]:
|
||||
held = _STEADY.get()
|
||||
if held is None:
|
||||
return _stamps(folder)
|
||||
if folder not in held:
|
||||
held[folder] = _stamps(folder)
|
||||
return held[folder]
|
||||
|
||||
|
||||
def _stamps(folder: Path) -> dict[str, tuple]:
|
||||
@@ -84,6 +108,8 @@ def forget() -> None:
|
||||
_BLOCK.clear()
|
||||
_BASE.clear()
|
||||
_MARKED.clear()
|
||||
if (held := _STEADY.get()) is not None:
|
||||
held.clear()
|
||||
|
||||
|
||||
def stale(names, marks=()) -> None:
|
||||
@@ -97,6 +123,8 @@ def stale(names, marks=()) -> None:
|
||||
if was.get("그룹") != "로직":
|
||||
_MARKED.setdefault(name, set()).update(marks)
|
||||
_INDEX.pop("자국", None)
|
||||
if (held := _STEADY.get()) is not None:
|
||||
held.clear()
|
||||
|
||||
|
||||
def loaded(folder: Path) -> tuple[dict[str, dict], object]:
|
||||
@@ -105,7 +133,7 @@ def loaded(folder: Path) -> tuple[dict[str, dict], object]:
|
||||
if _INDEX.get("폴더") != folder: # 시험은 사본 폴더로 바꿈
|
||||
forget()
|
||||
_INDEX["폴더"] = folder
|
||||
now = _stamps(folder)
|
||||
now = _now(folder)
|
||||
for gone in [name for name in _READ if name not in now]:
|
||||
del _READ[gone]
|
||||
for name, stamp in now.items():
|
||||
|
||||
Reference in New Issue
Block a user