Skip to content

perf: 레이아웃 캐시가 화면에 있는 것만 쥔다 (8,000문단 270→39 MB) - #58

Merged
centwon merged 4 commits into
mainfrom
perf/layout-cache-measure-split
Sep 29, 2026
Merged

centwon merged 4 commits into
mainfrom
perf/layout-cache-measure-split

Conversation

@centwon

@centwon centwon commented Sep 29, 2026

Copy link
Copy Markdown
Owner

요약

PR #57의 후속이다. 그 PR이 남긴 "캐시가 문서 전체의 레이아웃을 쥔다"를 해결한다.

  • 측정·페이지 나눔·지나가기만 하는 워크(히트테스트·링크·블록 찾기)는 레이아웃 대신 높이 캐시(ConditionalWeakTable)를 읽는다.
  • 렌더는 그리는 문단만 셰이핑하고, 렌더 뒤 레이아웃 캐시를 최근 사용 256개로 트림한다(그 프레임이 쓴 것은 빼지 않음 — 보이는 표는 셀을 다 그린다).
  • 페이지 나눔은 쪽 경계를 넘는 문단만 줄 끝을 읽는다(LineBottoms, 높이와 함께 캐시).

실측 (LayoutCacheProbe D, 800×600 창, real Skia, RICHEDITOR_PERF=1)

main 이 PR
8,000문단 로드 레이아웃 8,000개, 270 MB 29개, 39 MB
8,000문단 끝까지 스크롤 8,000개, 276 MB 343개, 45 MB
스크롤 쪽당 (8,000 / 2,000문단) 29–36 / 10–11 ms 29–41 / 14–15 ms

2,000문단 스크롤 +4 ms/쪽은 다시 화면에 들어온 문단을 재셰이핑하는 비용이다(main은 로드 때 전부 셰이핑하고 전부 쥐고 있었다). 높이는 캐시에 남아 있어 아무것도 움직이지 않는다.

새 퍼즈 오라클이 찾은 결함 2건

편집을 거친 편집기의 측정 높이가 같은 문서를 새로 받은 편집기와 같아야 한다.

  • 목록 토글이 옛 높이를 남김: 목록 명령이 InvalidateVisual만 불렀다(여백이 줄 폭을 줄이는데).
  • 서명 해시 상쇄: NaN→1.5처럼 double의 상위 비트만 다른 변경 두 개(문단 + 인라인 표 셀 줄 간격, 전체 선택 + 줄 간격)가 FNV에서 상쇄됐다(28쌍 중 1). SplitMix64 finalizer(Avalanche)를 거쳐 섞는다.

검증

  • 빌드 경고 0 · unit 1255 + render 55 그린 · 퍼즈 500시드 1회 그린(CI는 20)
  • 반증(되돌리면 빨강): Avalanche → 서명 테스트 · 목록 InvalidateMeasure → 목록 테스트 + 퍼즈 2시드 · 인라인 표 _heightCache.Remove → 기존 인라인 표 리사이즈 2건 · 트림/높이 캐시 → 상한 테스트 2건 · 작업집합 보호 → 400셀 표 테스트
  • 정리: 임시 계측(DebugLog, TempSigProbe) 제거, 헤드리스 Window.Close() 두 곳 제거(마지막 top-level을 닫으면 디스패처가 내려감)

⚠ 브랜치에 wip: 커밋이 섞여 있으니 squash merge를 권한다.
GUI 실기 확인 권장: 긴 문서 스크롤·목록 토글·표 안 편집.

🤖 Generated with Claude Code

centwon and others added 4 commits September 28, 2026 20:47
측정·페이지 나눔·지나가기만 하는 워크는 높이 캐시(약참조)를 읽고, 렌더는
그리는 문단만 셰이핑하며, 렌더 뒤 최근 사용 256개로 트림한다(그 프레임이 쓴 것은 제외).
8,000문단: 270 MB -> 39 MB, 끝까지 스크롤해도 45 MB.

퍼즈에 높이 오라클(편집한 편집기 = 새 편집기 측정 높이)을 넣어 찾은 결함 2건:
- 목록 토글이 InvalidateMeasure를 안 불러 옛 높이가 남음
- NaN->값처럼 상위 비트만 다른 두 변경이 서명 해시에서 상쇄(1/28) -> Avalanche 혼합

임시 계측(DebugLog, TempSigProbe) 제거, 헤드리스 Window.Close() 제거.
반증: Avalanche·목록 측정·높이 캐시 무효화·트림·작업집합 보호 각각 되돌리면 빨강.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@centwon
centwon merged commit 1dbe737 into main Sep 29, 2026
4 checks passed
@centwon
centwon deleted the perf/layout-cache-measure-split branch September 29, 2026 21:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant