diff options
| author | eunhhu <[email protected]> | 2026-10-19 08:05:53 +0100 |
|---|---|---|
| committer | eunhhu <[email protected]> | 2026-10-19 08:05:53 +0100 |
| commit | 4a7e780278df740e5e37c3307fe687405df72448 (patch) | |
| tree | ab56d72029970669416705cd5ea7c50f9caffbf3 /docs/research | |
| parent | 1c1133ce8258dad367aad3b7c8eee0083aecf772 (diff) | |
| download | pure-4a7e780278df740e5e37c3307fe687405df72448.tar.gz pure-4a7e780278df740e5e37c3307fe687405df72448.zip | |
140: LIST_VALUE's copy reviewed before building (measured by spec: UAX #14 about 10% of its time, JSON tree 6%, HTTP 2%, inflate 0.06%, the rest none; the cost a tree built item by item, 64 ns an item and 250 ns a copy): lend and detach (CoW) noted as the decision point (a branch on every event list's change for 10/6/2/0/0/0), a compile-time move ruled out (it changes LIST_VALUE's contract), the arrays copied whole built (UAX #14 -6.8%, its share to about 3%); 041's five works within 0.03% (b49, b50), the bank's queries within 0.3% (s49, s50), noise between builds larger
Diffstat (limited to 'docs/research')
| -rw-r--r-- | docs/research/140-spec-suite.md | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/docs/research/140-spec-suite.md b/docs/research/140-spec-suite.md index 9cbe5c2..da1f562 100644 --- a/docs/research/140-spec-suite.md +++ b/docs/research/140-spec-suite.md @@ -959,6 +959,69 @@ min과 max가 남는다. Flexbox의 어려운 반은 크기가 아래에서 위� - aup에 두는 것: 축을 필드 번호로 고르기(배치의 마찰 3), `number`나 `send` 같은 이름. 이름은 타입과 말의 자리를 지키려고 그대로 둔다. - 원본: `2026-10-19-frictions.jsonl`(검사, 전과 뒤의 명령과 시간, 줄). aup의 설계 002 "140의 마찰을 걷어 냄". +## LIST_VALUE의 복사를 다시 봄 (2026-10-19) + +리스트 값(let의 리스트를 fn에 넘기거나 레코드에 담기)은 항목을 복사한다. 여러 명세에서 그 값이 보였다. 새 명령 없이 줄일 수 있는지 +설계부터 보고, 실익이 분명한 것만 만들었다. + +**잰 것.** 계측한 빌드(연구용, 커밋하지 않음)로 명세마다 LIST_VALUE의 시간 몫을 쟀다(시계의 값은 대략 뺐다). + +| 명세 | 한 번 돌 때의 LIST_VALUE | 원본의 꼴 | 시간 몫 | +|---|---|---|---| +| UAX #14 | 168,048번(줄마다 9번, 평균 3.3항목) | FLAT 배열 | 약 10% | +| JSON 트리 | 4,001번 | 트리(리스트를 담은 레코드) | 약 6% | +| HTTP/1.1 | 596번 | 트리(바이트를 담은 레코드) | 약 2% | +| inflate | 9번 | FLAT 배열 | 0.06% | +| DNS, JSON 검사기, 상자 배치 | 0 | — | 0 | + +- **원인.** `nest()`가 원본의 꼴과 상관없이 새 리스트를 트리로, 항목을 하나씩 넣어 지었다. 항목당 약 64 ns였고, 한 번에 약 250 ns의 + 고정 비용(새 리스트의 할당과 초기화)이 더 들었다. 수 8바이트를 베끼는 값이 아니라 트리에 넣는 값이다. + +**검토한 셋.** +1. **빌려주고 뗀다(CoW).** 리스트 값이 원본의 리스트를 그대로 가리키고, 원본이 바뀌기 전에 떼어 낸다. 복사가 없어질 수 있는 유일한 + 길이다. 다만 비용이 넓다. + - 실행기에서 이벤트 리스트를 바꾸는 모든 자리에 갈래가 하나씩 는다. LIST_APPEND는 어디서나 뜨겁다. + - `drop_nested`가 누구의 리스트를 놓을지 가려야 한다. + - `nested.shared`를 세서, APPEND_IN이 빌린 값을 통해 let의 리스트에 쓰지 않게 해야 한다. + - 블록 안의 let 리스트가 반복마다 도는 비우기 고리가 떼어 내기를 부른다. + - 그 값으로 얻는 것은 10%, 6%, 2%, 0, 0, 0이다. 지금은 만들지 않고 결정점으로 남긴다. +2. **컴파일 때 옮긴다.** aup가 let 리스트의 마지막 쓰임을 알아 LIST_VALUE를 "옮기기"로 낸다. LIST_VALUE의 뜻(명령의 계약)을 바꾸므로 + 이번의 규칙(새 명령도 계약의 변경도 없이) 밖이다. 적어만 둔다. +3. **배열을 통째로 복사한다(만들었다).** 원본이 FLAT 배열이고 키가 없고 칸이 수, bool, i64뿐이면, 열마다 memcpy로 새 리스트를 + 짓는다(`pure_list_copied`). 내부 표현일 뿐이라 명령도 모듈의 꼴도 검증기도 그대로다. 리스트 값을 쓰지 않는 일에는 닿지 않는다. + +**결과.** + +| 복사 하나 | 전 | 뒤 | +|---|---|---| +| 3항목 | 540 ns | 320 ns | +| 60항목 | 3,926 ns | 324 ns | +| 600항목 | 38,268 ns | 985 ns | + +(계측한 빌드의 값이다. 시계 값으로 한 번에 100–150 ns가 더 들어 있다.) + +| 명세 | 코드 포인트·바이트당 ns 전 → 뒤 | 명령 | +|---|---|---| +| UAX #14 | 6,917 → 6,445(**−6.8%**) | 같다(1,774.3) | +| JSON 트리 | 606.0 → 607.4 | 같다 | +| HTTP/1.1 | 270.6 → 270.5 | 같다 | +| inflate | 895.0 → 895.2 | 같다 | + +- UAX #14의 LIST_VALUE 몫은 약 10%에서 약 3%로 줄었다. 남은 것은 한 번의 고정 비용(할당)이다. +- JSON 트리와 HTTP는 그대로다. 원본이 트리이고(레코드에 리스트나 바이트가 들었다), 리스트를 담은 레코드는 칸마다 공유 수를 센다. +- **남은 결정점.** 셋이 있다. 모두 지금은 만들지 않는다(얻는 것이 3% 이하, 6% 이하). + - 리스트 값의 리스트를 사건마다 새로 할당하지 않고 다시 쓰기(UAX #14의 남은 약 3%). + - 트리의 잎을 통째로 복사하기(JSON 트리, HTTP). + - 빌려주고 떼기. +- **검사.** `test-module`의 `copied_lists`가 무작위 리스트(좁고 넓은 수, bool, i64)를 복제해 하나씩 넣은 것과 같은지 보고, 복제본과 + 원본을 따로 바꿔 서로 닿지 않는지 본다. 트리, 키, 텍스트는 그렇게 복사하지 않는다. ASan에서도 지난다. aup의 `make check`(리스트 + 값, 블록 안의 리스트, 저장되는 중첩)와 Pure의 `make check`가 지난다. +- **다른 일에 닿지 않는다.** 041의 다섯 일(b49 대 b50, 3라운드의 사용자 모드 명령)은 묶음과 라운드 두 길 모두 ±0.03% 안이다. + 가장 큰 것이 묶음의 knapsack +0.023%다. 은행 질의(s49 대 s50, 025의 count.py, 둘씩 번갈아)는 모두 0.3% 안이다(in_credit + +0.26%, per_branch +0.15%). 같은 빌드끼리의 흔들림(per_branch 0.47%)보다 작다. 리스트 값을 쓰지 않는 일이므로 바뀌지 않는 것이 + 맞다. +- 원본: `2026-10-19-list-value.jsonl`, 041의 `2026-10-19-counts.jsonl`(b49, b50), 040의 `2026-10-19-counts.jsonl`. + ## 착수 기준 (다음 일) - **바꿀 결정.** 계산의 핵을 설계한다(027). 위 표의 여덟 후보 가운데 무엇을 어떤 모양으로 받을지 정한다. |
