1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
# Pure 012: 실행 입력이 편집기를 다시 계산하던 경로 제거
작성일: 2026-09-23. 실제 작성 도구 변경, 단계별 프로파일과 브라우저 비교.
## 알아낸 것과 바뀐 동작
011에서 DOM 재생성을 없앴지만 시간이 줄지 않았다. 다음 변경에 앞서 비용을 나눠 측정하니
출력 계산·전달보다 **바뀌지도 않은 소스 편집기의 정보를 갱신하는 경로**가 더 컸다.
입력 이벤트마다 `refresh()`가 줄 번호, UTF-8 바이트 수, 스크롤, 커서 위치를 갱신했다.
입력과 코드 편집은 독립적인데 하나의 갱신 함수로 묶여 있었다.
실행 갱신에서 이 경로를 제거했다. 실제 소스 변경에서만 편집기 정보를 갱신하고,
코드 적용은 초안과 적용된 정의의 일치 상태만 갱신한다.
화면에 이미 같은 값이 있으면 상태·진단·버튼 속성도 다시 쓰지 않는다.
새 캐시, 구독 그래프, 이벤트 버스, VM 명령이나 런타임 계층을 추가하지 않았다.
사용자는 전과 같이 코드를 작성하고, 키보드·화면 버튼·프레임으로 동작시킨다.
실행 중에도 미적용 초안은 그대로 남고 코드 편집·적용·오류 위치 이동의 표시가 갱신된다.
이번 결과는 **불필요한 갱신 연결을 제거한 구현 개선**이다. 새로운 계산 원리의 발견은 아니다.
## 먼저 확인한 비용
24개 출력, 상태 하나, 입력 하나를 작성했다. 이동 입력은 x를 0.25 늘리고 도형과 텍스트에 반영된다.
준비 입력 20회 뒤 입력 100회(누름·해제 200사건)를 처리했다.
기존 app 모듈의 테스트 전용 응답에 타이머를 삽입해 한 차례 프로파일했다.
| 구간 | 호출 수 | 누적 시간 |
|---|---:|---:|
| 계산·출력 전달 `present` | 200 | 26.6 ms |
| 비용 표시 | 200 | 56.6 ms |
| 편집기 정보 갱신 | 200 | 259.1 ms |
| 전체 `refresh` | 200 | 359.6 ms |
전체 입력 묶음은 375.9 ms였다. 부분 구간은 refresh 안에 포함되므로 합산하지 않는다.
CDP는 이 구간 주변에서 레이아웃 201회와 레이아웃 시간 177.7 ms를 기록했다.
줄 번호를 쓴 뒤 스크롤 위치를 읽는 경로도 있었다. 이 관찰을 근거로 편집기 갱신 연결을
먼저 제거했으며, 바인딩 캐시나 출력 평가 정책은 변경하지 않았다.
## 변경 전후 비교
직전 구현의 소스를 보존했다. before 실행에서는 app.js만 테스트 응답으로 교체한다.
런타임·출력 어댑터·컴파일러·Wasm·작성된 소스는 양쪽이 동일하다.
프로파일 타이머는 이 비교에 넣지 않았다. 인코딩 호출과 편집기 DOM 변경을 계측했다.
before/after 순서를 섞어 각각 3회 실행했으며 최종 상태·출력·이벤트 수와 실제 SVG 위치가 모두 같았다.
| 입력 100회당 관찰값 | 이전 | 현재 |
|---|---:|---:|
| 소스 UTF-8 인코딩 호출 | 400 | **0** |
| 인코딩 결과 배열의 누적 바이트 | 410,800 B | **0 B** |
| 편집기 정보의 DOM 변경 기록 | 800 | **0** |
| CDP 레이아웃 횟수, 매 실행 | 201 | **1** |
| 동기 처리 시간 중앙값 | 837.9 ms | **152.8 ms** |
| 동기 처리 시간 범위 | 709.7–1,151.8 ms | **137.8–327.4 ms** |
중앙값 기준 약 81.8% 감소다. 세 표본 모두 현재 쪽 시간이 더 짧았다.
다만 표본 수가 작고 편차가 크며 CPU·전력·다른 프로세스를 고정하지 않았다.
이 수치는 동일 세션의 **동기 합성 입력 dispatch부터 DOM 제출까지**다.
실제 키 입력 도착부터 화면 표시까지의 지연이나 큰 앱의 처리량으로 일반화하지 않는다.
계측 자체의 비용도 포함한다. CDP 카운터는 입력 묶음 전후의 브라우저 작업을 포함할 수 있다.
이전 보고서의 별도 실행 시간과 비율을 곱하거나 서로 직접 비교하지 않는다.
410,800 B는 없어진 인코딩 결과의 누적 용량이다. 피크 RAM 절감량도 전체 복사 바이트도 아니다.
추가 런타임 버퍼는 없다. app.js의 비압축 소스는 16,014 → 16,510 B로 496 B 증가했다.
코어·Wasm·011의 792 B 출력 버퍼와 바인딩 평가 순서는 그대로다.
## 보존한 계약과 검사
소스 입력, Tab 삽입, 코드 조각·파일·예제 삽입은 편집기 정보 갱신 경로를 사용한다.
성공·실패한 코드 적용은 초안 상태를 다시 확인한다. 커서 이동·스크롤·오류 위치 이동은
해당 표시만 갱신한다. 실행 입력·프레임·초기화는 소스 내용을 재계산하지 않는다.
UI의 오류 문구는 완성된 문자열을 한 번에 갱신하고 기존 사건 오류·표시 오류 구분을 유지한다.
브라우저 비교·편집 분리 검사 13개, 기존 작성 흐름 44개, 표시 한도·복구 12개가 통과했다.
검사에는 Unicode 바이트 수, 줄 번호, 미적용 초안을 둔 실행·초기화, 성공/실패 적용,
오류 위치 이동, Tab·코드 조각 삽입, 저장·복원, 키보드·포인터·모바일 동작이 포함된다.
Zig·컴파일러·런타임은 변경하지 않았으므로 기존 52개 JS/CLI/Wasm 검사나 네이티브 검사를
다시 실행한 것으로 세지 않는다. 이번 변경의 검증은 실제 브라우저에서 수행한다.
- [변경 전 소스·해시](../../prototypes/workbench/results/2026-09-23-refresh/before/manifest.json)
- [현재 소스·검증 기록](../../prototypes/workbench/results/2026-09-23-refresh/verification.json)
- [원인 프로파일](../../prototypes/workbench/results/2026-09-23-refresh/profile-before.json)
- [6회 비교와 편집 분리 검사](../../prototypes/workbench/results/2026-09-23-refresh/browser.json)
- [작성 흐름 검사](../../prototypes/workbench/results/2026-09-23-refresh/browser-authoring.json)
- [표시 한도·복구 검사](../../prototypes/workbench/results/2026-09-23-refresh/browser-limit.json)
- [비교 절차](../../prototypes/workbench/qa-refresh.js), [실행 스크립트](../../prototypes/workbench/qa-refresh.py)
```sh
python3 prototypes/workbench/qa-refresh.py --cli /path/to/playwright-cli.js --session pure-path --output /tmp/pure-refresh-new.json
```
사전에 로컬 페이지를 연 Playwright CLI 0.1.21 세션이 필요하다. 결과 파일은 덮어쓰지 않는다.
검사 종료 후 원래 모듈과 빈 작업물로 복원한다.
## 결정과 남은 범위
실행과 편집의 갱신 경로 분리를 채택한다. 현재 질문에 답했으므로 같은 입력의 추가 측정은 하지 않는다.
이 결과를 ‘모든 추상화 제거가 빠르다’는 근거로 삼지 않는다. 비용이 컸던 것은 실제로 변하지 않은
편집 자료까지 갱신하도록 연결한 경로였다. 필요한 연결과 수명은 유지한다.
전체 표시식 평가·비용 숫자 포맷·호스트 진단 생성은 남아 있다. 자동으로 다음 미세 최적화에 들어가지 않는다.
다음 인터페이스 확장은 사용자가 대상과 관계를 직접 조작하는 실제 요구를 기준으로 잡는다.
|