perf(B04): 등고선 피처 풀기를 한 번만 (격자와 무관)
PLAN 0-10. 「등고선 굽기」가 확장 8회 합 19s 였는데, 실측해 보니 굽기 자체는 0.8~2.0s 이고 나머지는 **피처 4,200개를 회차마다 다시 `shape()` 로 푸는 값**이었음. 푸는 결과는 격자와 무관하므로 같은 목록·같은 하한이면 그대로 쓴다(목록 객체를 함께 들고 있어 id 가 다른 목록에 재사용되지 않음, 최근 2벌만 보관). 실측 — 같은 격자 연속 4회: 2.66 · 1.90 · 1.99 · 2.03s (2회차부터 파싱 재사용), 결과 배열은 4회 모두 동일. `build_contour_descent` 전체는 옛 코드 12.8s → 7.2s 이며 band_elevation·valid·receiver·step_length·azimuth·levels 전부 `np.array_equal` 동일. 안 한 것 — 격자가 커질 때 옛 굽기를 옮겨 붙이고 **테두리만** 굽는 안은 만들어 재 봤으나 `rasterize` 호출당 고정 비용 때문에 오히려 3.2s → 10.6s 로 느렸고, 창에 걸치는 선만 넘기도록 고쳐도 3.8s 로 손해였음(창 4개 × 166단). 그래서 걷어내고 파싱 캐시만 남김. `levels` 는 피처 전체에서 나오므로 격자와 무관하다는 것도 확인함. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -72,12 +72,25 @@ class ContourDescent:
|
||||
levels: list[float] # 사용된 등고 표고(내림차순)
|
||||
|
||||
|
||||
def rasterize_contours(
|
||||
spec: GridSpec,
|
||||
contour_features: list[dict[str, Any]],
|
||||
elevation_floor_m: float | None = None,
|
||||
) -> tuple[np.ndarray, list[float]]:
|
||||
"""등고선을 격자에 굽는다. 셀마다 그 위를 지나는 등고 라인의 표고(없으면 NaN)."""
|
||||
_LINES_CACHE: list[tuple[Any, int, float | None, dict[float, list[Any]]]] = []
|
||||
|
||||
|
||||
def _lines_by_level(
|
||||
contour_features: list[dict[str, Any]], elevation_floor_m: float | None
|
||||
) -> dict[float, list[Any]]:
|
||||
"""등고선 피처를 표고별 선 묶음으로 푼다 — **격자와 무관**하므로 한 번만 푼다.
|
||||
|
||||
확장 회차마다 다시 부르는데 피처 4,200개를 매번 `shape()` 로 푸는 비용이 그대로
|
||||
붙었다. 같은 목록·같은 하한이면 그대로 돌려준다(목록 객체를 함께 들고 있어 id 가
|
||||
다른 목록에 재사용되지 않는다).
|
||||
"""
|
||||
for holder, count, floor, cached in _LINES_CACHE:
|
||||
if (
|
||||
holder is contour_features
|
||||
and count == len(contour_features)
|
||||
and floor == elevation_floor_m
|
||||
):
|
||||
return cached
|
||||
by_level: dict[float, list[Any]] = {}
|
||||
for feature in contour_features:
|
||||
geometry = feature.get("geometry")
|
||||
@@ -96,7 +109,18 @@ def rasterize_contours(
|
||||
if line.length < DRAINAGE_CONTOUR_MIN_LENGTH_M:
|
||||
continue
|
||||
by_level.setdefault(float(elevation), []).append(line)
|
||||
_LINES_CACHE.append((contour_features, len(contour_features), elevation_floor_m, by_level))
|
||||
del _LINES_CACHE[:-2]
|
||||
return by_level
|
||||
|
||||
|
||||
def rasterize_contours(
|
||||
spec: GridSpec,
|
||||
contour_features: list[dict[str, Any]],
|
||||
elevation_floor_m: float | None = None,
|
||||
) -> tuple[np.ndarray, list[float]]:
|
||||
"""등고선을 격자에 굽는다. 셀마다 그 위를 지나는 등고 라인의 표고(없으면 NaN)."""
|
||||
by_level = _lines_by_level(contour_features, elevation_floor_m)
|
||||
burned = np.full((spec.n_rows, spec.n_cols), np.nan, dtype=np.float32)
|
||||
levels = sorted(by_level, reverse=True)
|
||||
transform = grid_transform(spec)
|
||||
|
||||
Reference in New Issue
Block a user