diff options
| -rw-r--r-- | CHECKPOINT.md | 5 | ||||
| -rw-r--r-- | docs/research/115-apps-that-change.md | 33 | ||||
| -rw-r--r-- | research/experiments/040-against-c/2026-10-19-counts-s51.jsonl | 4 |
3 files changed, 37 insertions, 5 deletions
diff --git a/CHECKPOINT.md b/CHECKPOINT.md index 9c3732d..ca027f0 100644 --- a/CHECKPOINT.md +++ b/CHECKPOINT.md @@ -35,7 +35,7 @@ +9%, 상주 −10%, [107](docs/research/107-snapshot-nodes-reused.md)). 남은 가장 큰 몫은 항목 찾기다. 키로 나눈 소유자는 그다음에 본다. 대신 압축한 파일이 한 주기의 0을 미리 가져 커밋이 새 블록을 받지 않는다(저장소 커밋 +21%, 저널 커밋 −59%, [085](docs/research/085-cycle-sized-files.md)). -남은 것: macOS의 호스트(`pure-serve`는 리눅스의 것), 바뀐 모듈을 놓기(바꿀 때마다 19 KB, 115), 압축을 없애는 제자리 재사용 저장소(085 다음), 응답을 기다리는 출력의 묶음 전달(083), 앱 +남은 것: macOS의 호스트(`pure-serve`는 리눅스의 것), 압축을 없애는 제자리 재사용 저장소(085 다음), 응답을 기다리는 출력의 묶음 전달(083), 앱 라우트의 TLS(앞단이 한다; 문서 피어의 TLS는 있다), HTTP로 앱을 더하고 바꾸는 길, aup·Vega의 배포 묶음, 캐시보다 큰 목록을 찾는 걸음(109: 미리 가져오기로는 줄지 않았다. 한 사건의 조회를 겹치거나 구조를 바꿔야 한다). @@ -72,8 +72,7 @@ **묶음과 쓰는 길(위의 "남은 것", 바깥 피드백 006).** - 진입점이 하나가 아니다. aup는 `check`, `build`, `watch`, `query`다. `aup run`도, 런타임을 담은 단일 실행 파일도 없다. `pure-run`은 시험용이고(제품 인터페이스가 아니다), 운영은 `pure-serve`다. -- 그 밖에 남은 것: aup와 Vega의 배포 묶음, HTTP로 앱을 더하고 바꾸는 길, 앱 라우트의 TLS(앞단이 한다), 바뀐 모듈 놓기(교체마다 - 19 KB), 압축 없는 제자리 재사용 저장소, 응답을 기다리는 출력의 묶음 전달, 캐시보다 큰 목록 찾기. +- 그 밖에 남은 것: aup와 Vega의 배포 묶음, HTTP로 앱을 더하고 바꾸는 길, 앱 라우트의 TLS(앞단이 한다), 압축 없는 제자리 재사용 저장소, 응답을 기다리는 출력의 묶음 전달, 캐시보다 큰 목록 찾기. - 다른 언어에서 부를 안정된 C ABI와 바인딩이 없다. `core/module.h`가 C에서 쓰는 길이고, 140의 시간 도구가 그것을 쓴다. **공개의 증거.** 아래 "공개할 작업물과 완료 증거" 표는 aup 이전의 문서 앱을 기준으로 적었다. 1.0의 증거 앱(Vega의 메신저, diff --git a/docs/research/115-apps-that-change.md b/docs/research/115-apps-that-change.md index 5a5ec1d..b5eae9e 100644 --- a/docs/research/115-apps-that-change.md +++ b/docs/research/115-apps-that-change.md @@ -112,7 +112,36 @@ B는 5xx를 하나도 받지 않았다. 바꾸는 일은 파일을 읽는 스레 ## 다음 -- **바뀐 모듈을 놓기.** 지금은 바꿀 때마다 19 KB가 남는다(하루 한 번 바꾸면 한 해 7 MB). 놓으려면 그 모듈로 해석된 요청이 - 끝났는지(본문을 받는 중인 요청은 `convert`에서 모듈을 다시 읽는다)와 연결 스레드의 리더가 다른 모듈로 옮겼는지를 알아야 한다. +- ~~**바뀐 모듈을 놓기.**~~ 했다(아래 "바뀐 모듈을 놓기"). + - **3b: 경로의 인증.** 앱의 경로를 누가 부를 수 있는지. 그 뒤에 HTTP로 앱을 더하고 바꾸는 길. - 기록의 모양이 바뀌는 큰 목록의 교체(100만 항목 172 ms)는 목록을 새 모양으로 다시 쓰는 값이다. 그동안 그 앱만 쉰다. + +## 바뀐 모듈을 놓기 (2026-10-19) + +바꿀 때마다 19 KB가 남던 것을 놓는다. 교체 4,000번에 교체당 0 B다(전: 19,284 B). 은퇴한 4,100개가 모두 놓였다. + +- **두 문제로 나눴다.** + - **같은지 묻기.** 여러 곳이 모듈의 주소로 "같은 모듈인가"를 물었다: 리더의 배치, 작업과 ViewJob의 route, 밀기 묶음, 링크, + 바인딩, 질의, 마지막 발행. 모듈을 놓으면 새 모듈이 그 주소에 올 수 있다. 그래서 모듈마다 프로세스 안의 일련번호(`serial`, + 읽을 때 붙고 다시 오지 않는다)를 두고 그것을 묻는다. + - **살아 있어야 하는 것.** 옛 모듈을 실제로 읽는 것은 셋뿐이다: 그것을 돌리는 앱, 그것의 스냅숏, 그것으로 해석된 처리 중인 + 요청. serve의 모든 앱 모듈은 쥠의 수를 가진 `Loaded`다. 스냅숏 하나와 요청 하나가 하나씩 쥔다. +- **놓는 때.** 바뀐 모듈은 은퇴하고, 앱을 바꾸는 스레드(`pure-apps`)가 셋이 모두 맞을 때 놓는다. + - 어떤 앱도 그것을 돌리지 않는다. + - 연결 스레드가 모두 은퇴 뒤에 고리를 한 번 시작했다(`resolve`가 모듈을 읽고 쥐기까지의 틈을 덮는다; 은퇴할 때 깨운다). + - 아무것도 쥐지 않는다. + 다른 앱의 링크는 받는 쪽의 잠금 안에서 묶고, 링크가 입력을 찾는 길은 `binding_lock` 안에서 읽는다. +- **검증.** + - `030/memory.py`: 위의 0 B. + - `030/stress.py`: 연결 스레드 셋, 뷰 작업자 하나. 보기 읽기 여섯(본문 있는 보기 둘), 밀기 둘, 교체를 가로지르는 본문 쓰기를 + 돌리며, 같은 크기의 세 모듈을 차례로 바꾼다. 600번 가운데 586번이 놓인 모듈의 주소에 실렸고, 답 85,535개가 모두 맞다. + ASan 빌드로 1,000번이 깨끗하다(ASan은 놓인 메모리를 격리해 주소가 다시 오지 않으니, 둘이 서로를 채운다). + - 주소로 되돌린 변이(리더, 보기 작업, 밀기 묶음)는 이 시험에서 틀린 답을 내지 않았다. 요청은 답할 때까지 모듈을 쥐어 그동안 + 주소가 다시 오지 않고, 놓기는 연결 스레드의 다음 고리를 기다린다. 번호는 쥐지 않고 오래 남는 참조를 위한 방어다. + - Pure와 Vega의 `make check`가 지난다. 은행 질의(s50 대 s51)는 모두 0.4% 안이고, 가장 가벼운 `none`이 실행마다 명령 50개 + 늘었다(+0.008%, 요청마다 쥐고 놓기). +- **함께 고친 것.** 앱이 다시 요청을 받기 전에 새 스냅숏을 발행해서, 그 사이에 돈 밀기 묶음은 조용하다고 보고 앱의 다음 저장까지 + 기다렸다(`server_view_workers`가 부하에서 한 번 떨어졌다). 요청을 받기 시작한 뒤 밀기를 한 번 더 깨운다. +- **남은 것.** 링크 리스너의 바인딩은 모듈마다 하나씩 쌓인다(입력마다 24 B). 놓인 모듈의 바인딩은 그 뒤 오는 것을 거절할 뿐이다. +- 원본: `030/2026-10-19-memory.jsonl`, `-stress.jsonl`, 040의 `2026-10-19-counts-s51.jsonl`. diff --git a/research/experiments/040-against-c/2026-10-19-counts-s51.jsonl b/research/experiments/040-against-c/2026-10-19-counts-s51.jsonl new file mode 100644 index 0000000..649f113 --- /dev/null +++ b/research/experiments/040-against-c/2026-10-19-counts-s51.jsonl @@ -0,0 +1,4 @@ +{"serve": "pure-serve", "per_branch": {"instructions": 26983340, "cycles": 12171011}, "in_credit": {"instructions": 3537377, "cycles": 1614240}, "large": {"instructions": 1410310, "cycles": 589536}, "ranks": {"instructions": 24512146, "cycles": 15462218}, "none": {"instructions": 617346, "cycles": 210440}, "field": {"instructions": 8887355, "cycles": 3120093}, "found": {"instructions": 14040660, "cycles": 10428095}} +{"serve": "pure-serve", "per_branch": {"instructions": 27026124, "cycles": 12029180}, "in_credit": {"instructions": 3547032, "cycles": 1616562}, "large": {"instructions": 1410304, "cycles": 597848}, "ranks": {"instructions": 24534881, "cycles": 14892953}, "none": {"instructions": 617396, "cycles": 190983}, "field": {"instructions": 8887405, "cycles": 3098437}, "found": {"instructions": 14038389, "cycles": 10564729}} +{"serve": "pure-serve", "per_branch": {"instructions": 27050931, "cycles": 12117857}, "in_credit": {"instructions": 3552702, "cycles": 1636119}, "large": {"instructions": 1410230, "cycles": 590561}, "ranks": {"instructions": 24551305, "cycles": 14876285}, "none": {"instructions": 617346, "cycles": 189750}, "field": {"instructions": 8887356, "cycles": 3109413}, "found": {"instructions": 14036699, "cycles": 10520758}} +{"serve": "pure-serve", "per_branch": {"instructions": 26881756, "cycles": 11912110}, "in_credit": {"instructions": 3514778, "cycles": 1579936}, "large": {"instructions": 1410280, "cycles": 669195}, "ranks": {"instructions": 24457696, "cycles": 15909436}, "none": {"instructions": 617396, "cycles": 209921}, "field": {"instructions": 8887508, "cycles": 3175522}, "found": {"instructions": 14038758, "cycles": 10230479}} |
