From b1ce1927022d374198441afafeb27199fc8a052a Mon Sep 17 00:00:00 2001 From: eunhhu Date: Thu, 24 Sep 2026 17:14:54 +0100 Subject: Establish native micro runtime checkpoint --- docs/research/036-gtk-memory-boundary.md | 89 ++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 docs/research/036-gtk-memory-boundary.md (limited to 'docs/research/036-gtk-memory-boundary.md') diff --git a/docs/research/036-gtk-memory-boundary.md b/docs/research/036-gtk-memory-boundary.md new file mode 100644 index 0000000..d90246d --- /dev/null +++ b/docs/research/036-gtk-memory-boundary.md @@ -0,0 +1,89 @@ +# 036 — 선택형 문서 창의 메모리 경계 + +2026-09-24. 사용자가 원하는 것은 작은 **애플리케이션 런타임**이다. GTK 창의 +프로세스 비용을 코어의 비용처럼 취급하거나, 작은 압축 묶음만으로 메모리 목표를 +달성했다고 말할 수 없다. 여기서는 [035](035-native-multi-document-window.md)의 +1 MiB 문서 반복 전환에서 나타난 증가를 분리했다. 앱 기능을 추가하지 않았다. + +Linux AArch64에서 실제 GTK 창을 Xvfb 아래 띄우고, 1 MiB 문서 두 개를 +64회 열었다. 8회마다 `/proc//status` RSS와 `smaps`의 영역별 RSS를 +기록했다. 각각의 대조 실험은 같은 문서 앱의 저장·편집·충돌·정의 적용 +시나리오도 통과했다. RSS는 단일 실행의 관찰값이며, 실험 간 절댓값 차이를 +성능 순위로 해석하지 않는다. + +| 조건 | 8회 후 RSS | 64회 후 RSS | 힙 RSS 증가 | +|---|---:|---:|---:| +| 두 키, 서로 다른 1 MiB 본문 | 47,472 KiB | 58,896 KiB | 11,296 KiB | +| 같은 키 다시 열기 | 47,056 KiB | 47,072 KiB | 16 KiB | +| 두 키, 동일한 본문 | 47,216 KiB | 59,680 KiB | 12,464 KiB | +| 두 키, 1 MiB 전환 시 텍스트 뷰 갱신만 생략한 **진단 빌드** | 47,216 KiB | 47,216 KiB | 0 KiB | +| 두 키, 문서 버퍼 실행 취소 기능 비활성화 | 47,440 KiB | 59,008 KiB | 11,440 KiB | +| 두 키, 줄바꿈 비활성화 | 45,888 KiB | 57,440 KiB | 11,424 KiB | + +원자료는 순서대로 +[기본](../../prototypes/connections/results/2026-09-24-window-memory-analysis/smaps.json), +[같은 키](../../prototypes/connections/results/2026-09-24-window-memory-analysis/same-key.json), +[같은 본문](../../prototypes/connections/results/2026-09-24-window-memory-analysis/same-body.json), +[텍스트 갱신 생략](../../prototypes/connections/results/2026-09-24-window-memory-analysis/skip-text.json), +[실행 취소 비활성화](../../prototypes/connections/results/2026-09-24-window-memory-analysis/no-document-undo.json), +[줄바꿈 비활성화](../../prototypes/connections/results/2026-09-24-window-memory-analysis/no-wrap.json)에 있다. +텍스트 갱신 생략 빌드는 **문서를 제대로 보여주지 않으므로 제품 수정안이 아니다.** +키·버전·본문 복사·정의·저장 경로는 그대로 실행하고, 1 MiB의 다른 키를 열 때 +`gtk_text_buffer_set_text()` 호출만 건너뛰어 원인 경계를 분리했다. + +`mallinfo2`를 추가한 별도 진단 빌드에서는 glibc 할당기의 `uordblks`가 +8회 후 10,897,312 B에서 64회 후 23,427,504 B로 증가했다 +([원자료](../../prototypes/connections/results/2026-09-24-window-memory-analysis/mallinfo.json)). +따라서 관찰된 증가는 단순히 해제된 블록을 할당기가 보유하는 현상만으로 +설명되지 않는다. 반면 이 수치는 어떤 GTK 객체가 데이터를 소유하는지, +그 객체가 언제 반환되는지까지 밝히지 않는다. 종료 후 누수량과 실행 중 +힙 사용량도 같은 지표가 아니므로, 이 결과만으로 누수를 단정하지 않는다. + +GTK 문서는 [`GtkTextBuffer.set_text()`가 이전 내용을 지우고 새 내용을 넣으며 +실행 취소 불가능한 작업으로 표시된다](https://docs.gtk.org/gtk4/method.TextBuffer.set_text.html)고 +설명한다. 실행 취소와 줄바꿈을 각각 꺼도 증가량이 유지된 점과 함께 보면, +현재 위치는 **GTK 텍스트 교체 경계**다. 이전 버퍼를 새 버퍼로 바꾸는 실험도 +[035의 원자료](../../prototypes/connections/results/2026-09-24-multi-document-window/switch-memory-fresh-buffer.json)에서 +효과가 없었다. 특정 GTK 내부 캐시나 누수라는 결론은 내리지 않는다. + +재현 가능한 제품 빌드의 기준 경로는 +`make -C prototypes/connections window editor` 다음 +`xvfb-run -a python3 prototypes/connections/check_window.py --build prototypes/connections/build --program prototypes/connections/examples/editor.pure --switch-rounds 64 --diagnose-maps`다. +진단 변형은 제품 코드에서 제거했다. 텍스트 갱신 생략 변형은 +`open_document_key()`의 `gtk_text_buffer_set_text()` 앞에 +`if (!(strcmp(key, e->key) != 0 && e->baseline_size >= 1000000))`를 +놓되, 키 변경 전의 값을 비교해야 한다. 다른 변형은 창 생성 시 문서 버퍼에 +`gtk_text_buffer_set_enable_undo(buffer, FALSE)`를 호출하거나 문서 뷰의 +`GTK_WRAP_WORD_CHAR`를 `GTK_WRAP_NONE`으로 바꾼 것이다. `mallinfo2` +변형은 문서 열기 완료 직후 할당기 통계를 기록했다. + +현재 비용 경계는 분명하다. 기본 CLI의 1 MiB 작업에는 +[4 MiB 최대 RSS 검사](../../prototypes/connections/check_micro_memory.py)가 있고, +GTK·TLS는 기본 실행물에 링크되지 않는다. 선택형 GTK 창은 시작부터 약 +44 MiB RSS를 쓰고 위 반복 전환에서는 더 증가한다. 따라서 **이 창을 +마이크로 메모리 프로필이라고 부르지 않는다.** 선택형 창의 기능 검증은 +유효하지만 저메모리 UI를 증명하지 않는다. 큰 앱·서비스로 확장하기 전에 +실행 코어와 어댑터의 비용을 계속 따로 공개하고, UI에는 실제 화면·입력· +편집 기능을 유지한 상태에서 전환 후 메모리가 안정되는 구현이 필요하다. + +진단 코드를 제거한 최종 창도 [64회 전환 기능·RSS 검사](../../prototypes/connections/results/2026-09-24-window-memory-analysis/final-native-window.json)를 +통과했고, RSS는 8회 후 47,216 KiB에서 64회 후 58,528 KiB로 증가했다. +같은 상태의 `make check-release check-window-profile`에서는 코어 `text` +5,932 B, 기본 CLI의 1 MiB 편집 피크 RSS 2,080 KiB, 선택형 GTK 창의 +`text` 49,946 B가 각 회귀 상한을 통과했다. GTK 창의 코드 섹션 통과는 +전체 GTK 프로세스의 메모리 통과를 뜻하지 않는다. 이 결과를 반영해 다음 +GUI 기능을 추가하기 전에 창 메모리의 경계 또는 더 작은 네이티브 UI 어댑터를 +검증해야 한다. + +추가 대조에서 마지막 전환 후 10초간 창을 유휴 상태로 두어도 RSS는 +59,328→59,456 KiB로 줄지 않았다 +([원자료](../../prototypes/connections/results/2026-09-24-window-memory-analysis/settled-final.json)). +같은 1 MiB를 80 B 줄 대신 4,096 B 줄로 구성하면 8→64회 힙 RSS 증가가 +11,296 KiB에서 17,792 KiB로 오히려 커져, 단순한 **줄당 고정 비용** 가설도 +맞지 않았다 +([원자료](../../prototypes/connections/results/2026-09-24-window-memory-analysis/line-width-4096.json)). +전환마다 문서 `GtkTextView` 전체를 파괴·재생성한 진단 빌드 역시 힙 RSS가 +14,416→25,968 KiB로 증가했다 +([원자료](../../prototypes/connections/results/2026-09-24-window-memory-analysis/replace-view.json)). +이 세 실험은 GTK 내부 소유자를 특정하지 않는다. 뷰를 매번 재생성하는 +제품 코드는 채택하지 않았고, 작은 코어의 실행 모델 작업에 우선순위를 둔다. -- cgit v1.2.3