aboutsummaryrefslogtreecommitdiffstats
path: root/docs/research
diff options
context:
space:
mode:
Diffstat (limited to 'docs/research')
-rw-r--r--docs/research/115-apps-that-change.md33
1 files changed, 31 insertions, 2 deletions
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`.