- `docs/` 를 .gitignore 에서 빼 git 추적 대상으로 전환 (위키·완료 이력·검증 기록) - `docs/raw/PLAN.md` · `docs/raw/OWNERS.md` 를 저장소 최상위로 이동 후 .gitignore 에 등록 — 창끼리 공유하되 저장소에는 안 올리는 장부 - 살아 있는 경로 참조 7개 파일 정정 (아카이브 107건은 그때 사실이라 그대로 둠) - graphify 날짜별 산출물(`docs/wiki/graphify-out/20*/`) 제외 — `graphify update` 가 다시 만듦 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
145 lines
13 KiB
Markdown
145 lines
13 KiB
Markdown
# 유역 속도 개선 — 안 하기로 한 갈래 셋 (보관본)
|
||
|
||
**2026-09-07 사용자 판단으로 종료** — 「속도개선은 이제 안해도 될것같아. 충분히 빨라.
|
||
안한건 계획서에 삭제하고 항목 완료처리하자. 필요시 나중에 다시 하겠음.」
|
||
|
||
[확인] 한 번이 **293초 → 약 90초**가 된 상태에서 멈춘 것이며, 아래 셋은 **그 뒤로 더 줄이려던
|
||
갈래**다. 설계·실측이 다 되어 있으므로 다시 꺼낼 때 여기서부터 이어가면 된다.
|
||
계획서(`docs/raw/PLAN.md`) 0-11 에서 이리로 옮겼다 — 계획서에는 실측 표만 남겼다.
|
||
|
||
---
|
||
|
||
- [ ] (보류) 🔴 **다음 병목 — `expand_by_red_boundary`**. 2026-09-07 사용자가 목표를
|
||
구조물·계획노선 쪽으로 돌려 **유역 속도 작업은 여기서 멈춤**. 아래는 그때까지의 기록.
|
||
원래 102초(전체의 85%)였고 EDT 타일·등고선 캐시로 줄인 상태임. 확장 9회, 최종 셀
|
||
1,352,325개.
|
||
- **9회 중 7회가 격자를 넓힘** (로그 실측) — 1·2회차만 여유(`_pad_spec`, band_cells×2 =
|
||
100칸) 안에서 끝나고, 3회차부터 매번 `band_cells`(50칸)씩 커짐:
|
||
745×1035 → 795 → 845×1085 → 895×1135 → 945×1185 → 995×1235 → 1045 → 1095×1235.
|
||
격자가 커지면 `descent` 재사용 조건(`grown_spec == current`, `Expand.py:159`)이 깨져
|
||
**`build_contour_descent` 를 7번 통째로 다시 만듦**.
|
||
- 그 안은 `distance_transform_edt` 를 **등고 단계마다 한 번씩** 돎(`..._Descent.py:157~167`).
|
||
보조 창 계측에 따르면 단계가 **약 100개** — 격자 1,352,325셀 × 100회 = 회차 1번에만
|
||
1.35억 셀-연산. 이것이 7번 돎.
|
||
- **고칠 길 둘 — 갈림길은 계측이 정함**
|
||
ⓐ **EDT 창 좁히기(결과 보존)** — 쓰는 값은 `members`(그 밴드 셀)뿐이고 한 단 아래
|
||
등고선은 보통 수십 셀 안에 있음(주곡선 5m·셀 1m). `members` 바운딩박스를 여유만큼
|
||
넓힌 창에서만 EDT 를 돌리고, 나온 최대 거리가 여유에 닿으면 그 단계만 전체로 다시 돎
|
||
→ **결과가 반드시 같음**. 격자를 안 키우므로 아래 ⓑ 의 위험도 없음.
|
||
ⓑ **여유를 처음부터 크게 잡기** — 빠르지만 ⚠ **결과가 미세하게 달라짐**.
|
||
`build_contour_descent` 의 EDT 가 격자 전체를 보므로, 격자가 커지면 밖에 있던
|
||
등고선이 시야에 들어와 가장자리 셀의 밴드 표고가 바뀜 → 유역 면적·관경이 움직임.
|
||
**수량에 닿으므로 사용자 확인 전에는 안 감.**
|
||
- **계측으로 갈림길 확정** (2026-09-07, 보조 창 커밋 `5c22c367`) — **ⓐ 가 맞음.**
|
||
| 조각 | 초 | [확인] 116초 중 |
|
||
|---|---:|---:|
|
||
| **밴드별 하강거리 EDT** | **50.4** | **43%** |
|
||
| `classify_flow` | 25.7 | 22% |
|
||
| 등고선 굽기(`rasterize_contours`) | 16.3 | 14% |
|
||
| 1차 영역 | 4.4 | 4% |
|
||
| `_prepare` | 4.9 | 4% |
|
||
| B06 확정 | 2.5 | 2% |
|
||
| 나머지 | 6 | 5% |
|
||
|
||
방향장 1회 = 6.3s(745×1035) ~ 10.4s(1095×1235)이고 그중 EDT 가 66~75%.
|
||
8회 합계 69.4s. **시간은 셀 수가 아니라 격자 bbox 에 선형**(8·9회차는 셀이 거의 안
|
||
늘었는데도 13~14초). 재사용과 무관하게 도는 넷은 회차당 2.6s = 10회 25.7s인데
|
||
사실상 전부 `classify_flow` 임. 검산 69.4 + 25.7 = 95.1 ≈ 실측 95.8 ✅
|
||
- [x] **ⓐ 구현·검증 끝**(보조 창 커밋 `56d5fb26`) — 밴드별 EDT **10.8s → 2.9s(3.7배)**,
|
||
**값 완전 동일**.
|
||
- 첫 시도(밴드 바운딩박스 하나로 창 씌우기)는 **안 통했음** — `analyze_domain` 이
|
||
`build_contour_descent` 에 `domain` 을 안 넘겨 `inside` 가 격자 전체가 되고, 밴드가
|
||
격자 전역에 흩어져 바운딩박스가 사실상 격자 전체였음.
|
||
- 그래서 **타일로 쪼갬** — 밴드 셀을 타일로 나눠 타일마다 창을 씌우고, 타일별로 같은
|
||
폴백 장치(창 최대거리가 여유에 닿으면 그 타일만 전체 격자로). 채택값 **타일 256 · 여유 32**
|
||
(폴백 9/91). 근거표는 그 파일 주석에 남김.
|
||
- 검증 — 거리·목표행·목표열 91단 전부 `np.array_equal`, 옛 코드를 별도로 적재해
|
||
`build_contour_descent` 결과(`band_elevation`·`valid`·`receiver`·`step_length`·
|
||
`azimuth`·`levels`) 전부 동일. 시험 `tmp/tests/test_descent_edt_window.py` 11건.
|
||
- ⚠ 함정 — `distance_transform_edt(return_indices=True)` 가 주는 좌표는 **창 좌표**라
|
||
전체 격자 좌표로 옮겨 적어야 함. 안 하면 시간은 줄고 흐름 경로만 틀어져 **빨라졌다고
|
||
착각**하기 쉬움. 그래서 검증 기준을 「배열이 완전히 같은가」로 둠.
|
||
- 지금 남은 그림 ([확인] ≈ 100초 기준) — 확장 78~89s(**88%**) 안에서
|
||
방향장 재생성 8회 ≈ 50s(등고선 굽기 ≈ 19s · 밴드 EDT ≈ 16s · 나머지 ≈ 15s) ·
|
||
`classify_flow` 10회 ≈ 28s. 그 밖 `_prepare` 6s · 1차 영역 2~7s · B06 확정 4.4s · solve 2.4s.
|
||
- [ ] (보류) ② **`classify_flow`**(≈28s) — 재사용과 무관하게 회차마다 도는 유일한 큰 조각.
|
||
**2026-09-07 사용자가 목표를 구조물·계획노선 쪽으로 돌려 유역 속도 작업은 여기서 멈춤.**
|
||
[확인] 이 293초 → **약 90초**가 된 상태로 두고, 더 줄이는 것은 나중에 판단.
|
||
- **자리** — `_walk_from`(`..._Watershed_Flow.py:394`)이 셀 1,352,325개를 **파이썬 루프**로
|
||
훑음. 셀마다 수신 셀을 따라가는 사슬이라 전체로는 O(N) 이지만 파이썬이라 회차당 2.6초.
|
||
- **고칠 법(설계 확정)** — 이건 「함수형 그래프에서 뿌리 찾기」임. 각 셀은 수신 셀 하나만
|
||
가리키고, 사슬은 ⓐ 흡수 셀(도로·세류 → 적색) ⓑ 싱크(자기 자신 → 파랑) ⓒ 해석영역 밖
|
||
(→ 파랑) 셋 중 하나에서 끝남. 그러니 **포인터 더블링**(`nxt = nxt[nxt]` 를 고정점까지,
|
||
약 log₂N ≈ 20회)으로 전 셀의 뿌리를 한 번에 구하고 그 뿌리의 판정을 뿌리면 됨.
|
||
numpy 가져오기 20회 × 1.35M ≈ 0.1초 — **25배** 기대.
|
||
- **순서 무관함을 확인해 둠** — 겉보기에 순서에 걸리는 곳은 `:430` 의
|
||
`if not valid[following] and state[following] != 2` 하나뿐인데, 무효 셀이 `state==2` 가
|
||
되는 경우는 **세류 선확정 셀뿐**이고 그건 시작 전에 못박힘. 무효 셀은 `path` 에 절대
|
||
안 들어감(들어가기 전에 `state==2` 로 break). 그래서 단계 함수가 **정적**이고 벡터화가
|
||
정확함. 순환은 원래 코드도 파랑으로 처리하므로 더블링 반복 상한에 걸린 것을 파랑으로 두면 같음.
|
||
- ⚠ **막힌 곳 하나 — 진단 카운터 둘**. `outer_seeds`·`interior_seeds` 는 「1단계(최외곽
|
||
출발)가 몇 셀을 판정했나 / 2단계가 몇 셀을 판정했나」인데, 한 번에 푸는 방식에는 단계가
|
||
없음. 이 값을 그대로 내려면 「최외곽에서 출발한 사슬이 지나간 셀 집합」이 필요하고,
|
||
그건 함수형 그래프에서 **조상 집합 구하기**라 더블링으로는 안 나옴(같은 뿌리·같은 깊이여도
|
||
다른 가지일 수 있음). 닫힘 계산은 사슬 길이만큼 반복해야 해서 이득이 사라짐.
|
||
- **쓰는 곳 확인** — 두 값은 응답 페이로드와 TS 타입에만 있고 **계산에 쓰는 곳이 없음**
|
||
(`B04_PreProcess_Api_Fetch.ts:397`). 순수 진단값임.
|
||
- **그래서 결정** — 값을 바꾸는 일이라 **혼자 처리하지 않음**. 할 때는 ① `reaches`·
|
||
`analyzed`·`direction` 이 `np.array_equal` 로 같은지 증명하고 ② 두 카운터는 뜻이 바뀜을
|
||
사용자에게 알린 뒤(또는 필드를 없애기로 하고) 진행할 것.
|
||
- 안 하기로 한 것 ③ 방향장 자체를 옛 격자에서 옮겨 붙이기 — 이득은 가장 크나 코드·위험도
|
||
가장 큼. 위 둘을 끝내고 숫자를 다시 본 뒤 판단.
|
||
ode_modulesorest-road-webapp` → **저장소 루트 자신**
|
||
(npm 이 로컬 패키지를 링크하며 만든 것). 리로더가 B07 을 훑다가 그리로 되돌아가
|
||
`venv`·`storage` 를 다시 훑고 또 되감겼음.
|
||
- 실측 — 감시 폴더를 `rglob` 하면 파일 **486,809개**, 한 바퀴 **1,045초**. PowerShell 로
|
||
세면 `config` 4개·`B07` 23개뿐임. **파이썬 `rglob` 은 정션을 따라 들어가고 PowerShell 은
|
||
안 따라가서** 눈으로는 안 보였음.
|
||
- 갈래 실험 — 리로드 끔 **0%** / 켬 **64%** 로 갈렸음. 「앱이 먹는다」로 두 번 오진한 것은
|
||
프로세스 역할이 뒤바뀌어 보였기 때문임(띄운 것은 껍데기, 자식이 리로더, 손자가 서버).
|
||
- 고침 — `main.py` 의 `_reload_dirs` 가 ⓐ 소스 폴더만 보고(`351db312`) ⓑ `node_modules` 를
|
||
품은 폴더를 빼고(`e7d30327`·`7a1d7db6`) ⓒ **링크(정션) 폴더를 통째로 건너뛰게**(`70b25a5c`).
|
||
**CPU 85% → 18%**. ⓒ 로 정션이 또 생겨도 재발 안 함.
|
||
- 부작용 — **`main.py` 와 `config/` 를 고치면 자동 리로드가 안 됨.** 손으로 재시작할 것.
|
||
- 남은 18% 는 감시 탓으로 보기 어려움(감시 대상 파이썬 143개) — 급하지 않아 남겨 둠.
|
||
- 아직 안 한 것: `watchfiles` 설치(이벤트 방식, 거의 0%) — **사용자 허락 대기**.
|
||
- 창 둘이 각각 그러니 **기기가 늘 140% 눌린 채**임. 속도 계측이 회차마다 3배씩
|
||
흔들린(1차 영역 2.3s vs 29.4s) 진짜 배경으로 보임.
|
||
- 확인한 것 — 새로 띄운 직후에도, 몇 분 놀린 뒤에도 **63~74%**로 일정함.
|
||
로그는 한 줄도 안 늘어남. 메모리는 260 → 430MB 로 서서히 늚.
|
||
- **범인은 감시(리로더)가 아님** — 감시 프로세스는 **0%**, CPU 를 먹는 것은 **앱 프로세스**임
|
||
(`Get-NetTCPConnection` 이 가리키는 쪽이 앱 자식임을 부모-자식으로 확인).
|
||
- 배경 태스크 셋(세션 정리 1시간 · 리소스 계측 2분 · 임시파일 정리 6시간)은 전부 `sleep`
|
||
간격이 길어 후보가 아님.
|
||
- 스택을 떠 봤으나(리로드 없이 8099 로 따로 띄워 60초 뒤 `faulthandler`) **스레드 3개뿐이고
|
||
메인은 `run_forever` 에서 대기 중**이라 파이썬 층에서는 도는 것이 안 보였음.
|
||
→ C 확장이나 이벤트 루프 폴링 쪽일 가능성. `py-spy` 가 있으면 몇 초면 잡힐 자리인데
|
||
지금 환경에 없음. **설치 여부는 사용자 판단**.
|
||
- [x] 곁가지 하나는 고침(커밋 `351db312` + `7a1d7db6`) — 자동 리로드가 `storage`(27GB)·
|
||
`venv`(파이썬 파일만 7,530개)·`node_modules` 까지 0.25초마다 훑고 있었음. 파이썬이 사는
|
||
폴더만, 그중에서도 `node_modules` 를 품지 않은 것만 보게 함.
|
||
근거 — **루트 전체 훑기는 이 기기에서 300초에도 한 줄을 못 뱉음**(옛 방식이 0.25초
|
||
주기를 지킬 수 없었다는 뜻). 다만 기기가 계속 눌려 있어 정확한 전후 수치는 못 냈음.
|
||
⚠ 이것이 70% 를 고치지는 **못했음**. 감시 낭비만 걷어낸 것임.
|
||
(부작용 — **`main.py` 와 `config/` 를 고칠 때는 손으로 재시작**할 것. 둘 다 자주 고치는
|
||
자리가 아님.)
|
||
- ⚠ **측정 함정(2026-09-07 실사고)** — 내 8000 이 **옛 코드로 돌고 있었음**. uvicorn
|
||
StatReload 가 `..._Watershed_Stream.py` 변경을 안 물어, 고친 뒤에 잰 [확인] 이 **488초**로
|
||
나왔음(고치기 전 293초보다도 나쁨). 수정 로그가 한 줄도 안 찍힌 것으로 발각.
|
||
**속도를 재기 전에 ① 백엔드를 확실히 재시작하고 ② 그 수정의 로그가 실제로 찍히는지**
|
||
먼저 볼 것.
|
||
- [ ] (보류) **[확인] 이 유역을 안 기다리게 미루기** — 보조 창이 설계까지 마쳐 둔 안.
|
||
재측정이 여전히 느릴 때만 꺼냄. 요지: 기본 관 자리(`_base_pipes`)는 유역 해석과
|
||
무관하나 `build_detail`(`common_util_drainage_detail.py:184`)이 `read_road_routing`
|
||
없으면 404 라 통째로 막힘 → 관 목록만 담은 **얕은 갈래**를 하나 두고, `_base_pipes` 를
|
||
공용으로 옮겨 **한 벌**을 같이 부르게 함. `pipe_points.json` 에 `pending` 표식 하나.
|
||
⚠ **위험** — 배경 계산 중 사용자가 관을 만지면 `confirmed_chainages` 갈래를 타
|
||
`place_pipes` 를 아예 안 불러 **300m 규칙이 영구 미적용**됨. 막으려면 배경 채우기를
|
||
덮어쓰기가 아니라 **합치기**로 해야 함(보조 창 권고). 보충 관이 늘면 측점 재생성·B06
|
||
확정이 각각 1회씩 더 필요함.
|
||
**조사 결론(2026-09-07)** — 관 자리(`_base_pipes`)는 「도로 × 세류선 교차점」이라 무거운
|
||
흐름 해석과 무관함이 확인됨. 유역을 배경으로 미루면 [확인] 이 7초대까지 떨어질 수 있음.
|
||
그러나 위 ⚠ 위험 때문에 **지금은 안 감** — 대신 유역 자체를 줄이는 쪽(0-11 ①②)으로 감.
|
||
(윗줄과 같은 항목이라 하나로 합침.)
|
||
- ⚠ 속도개선 코드(코리도 캐시·묶음쓰기·`recompute_server_side`)는 계측 단계에서 **건드리지 않음**.
|