diff options
Diffstat (limited to 'docs/design')
| -rw-r--r-- | docs/design/017-apps-on-one-host.md | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/docs/design/017-apps-on-one-host.md b/docs/design/017-apps-on-one-host.md index f9ff765..3f2ce2b 100644 --- a/docs/design/017-apps-on-one-host.md +++ b/docs/design/017-apps-on-one-host.md @@ -1,7 +1,8 @@ # 017 — 한 호스트의 여러 앱: 차례, 예산, 실패 경계 작성일: 2026-10-01. 상태: 1·2단계와 2b 구현, 검사로 고정하고 쟀다([111](../research/111-apps-on-one-host.md), -[112](../research/112-sending-between-apps.md), [113](../research/113-one-sending-loop.md)). 3단계는 착수 기준을 적었다(2026-10-04). +[112](../research/112-sending-between-apps.md), [113](../research/113-one-sending-loop.md)). 3단계(수명) 구현, 검사로 고정하고 +쟀다([115](../research/115-apps-that-change.md)). 3b(경로의 인증)는 설계 전. [외부 리뷰 004](../outside-feedback/feedback-004.md)의 "구현 방향에 대한 평가" 셋째에서 시작한다. 작은 OS의 운영 모델( [007](007-execution-domains.md))을 Pure가 실제로 갖게 하는 단계다. @@ -238,17 +239,20 @@ counter apps/count.pmod stores/counter - 새 줄의 앱은 시작한다. 1단계의 시작과 같다(모듈 검증, 저장소, 배선, 실패하면 그 앱만 멈추고 까닭을 남긴다). - 없어진 줄의 앱은 멈춘다(아래의 순서). 그 뒤로 그 경로는 404 `no_app`이다. -- 바뀐 줄의 앱은 멈추고 새 줄로 다시 시작한다. 모듈 파일의 내용, 저장소, 예산, 배선 가운데 하나라도 바뀐 줄이다. 상태는 - 저장소에서 이름으로 이어받는다(지금 다른 모듈로 다시 띄울 때와 같다, `server_upgrade`). +- 바뀐 줄의 앱은 그 자리에서 바뀐다. 모듈 파일의 내용, 예산, 배선 가운데 하나라도 바뀐 줄이다. 받은 일을 다 적용하고 저장한 + 뒤, 메모리의 상태를 그대로 두고 모듈을 바꾼다(`pure_app_replace`: 상태와 outbox의 보냄을 이름으로 옮긴다). 저장소는 열린 + 채이고, 출구만 새 모듈로 다시 만든다. 새 모듈에 상태가 들어가지 않으면 그 앱은 멈추고 까닭을 남긴다. +- 저장소가 바뀐 줄의 앱, 저장이 불확실해진 앱은 멈추고 저장소에서 다시 연다(상태는 이름으로 이어받는다, `server_upgrade`). - 그대로인 줄의 앱은 건드리지 않는다. 멈춰 있거나(시작하지 못했거나) 불확실해진 앱만 다시 시작한다. 저장소에서 다시 연다. -- 다 맞추면 시작할 때와 같은 꼴의 줄 하나를 stdout에 낸다. 앱마다 상태와 까닭, 그리고 이번에 한 일(시작, 멈춤, 다시 시작)이다. +- 다 맞추면 시작할 때와 같은 꼴의 줄 하나를 stdout에 낸다(`{"reading":N,"apps":[…]}`). 앱마다 상태와 까닭, 그리고 이번에 한 + 일이다(kept, changed, restarted, started, removed). - 파일을 읽지 못하거나 틀린 줄이 있으면 아무것도 바꾸지 않고 까닭을 낸다. HTTP로 앱을 더하는 길을 두지 않는 까닭은 인증이다. 그 길은 경로의 인증(3b)을 먼저 요구한다. 신호는 프로세스의 주인만 보낼 수 있고, 파일은 호스트의 구성을 그대로 남긴다(다시 띄워도 같은 모습이다). 다시 읽기는 호스트의 스레드 하나(`pure-apps`)가 한다. 연결 스레드와 실행 스레드는 기다리지 않는다. -**멈추는 순서.** 앱 하나를 멈추는 것은 이렇다. +**멈추는 순서.** 앱 하나를 멈추는 것은 이렇다(그 자리에서 바꿀 때는 1–3까지 하고, 모듈을 바꾼 뒤 이어 간다). 1. 새 일을 받지 않는다. 그 앱의 경로는 503 `stopped`다. 링크와 안쪽 출구의 기록은 받지 않는다(보내는 쪽이 쥐고 다시 보낸다). 2. 소유자가 이미 받은 일을 다 적용하고, 저장하고, 답한다. @@ -279,11 +283,25 @@ HTTP로 앱을 더하는 길을 두지 않는 까닭은 인증이다. 그 길은 **하지 않는 것.** -- 끊김 없는 교체(새 모듈을 옆에서 띄우고 넘기기). 멈추고 다시 여는 동안 그 앱은 503을 답한다. 그 시간을 잰다. +- 끊김 없는 교체(새 모듈을 옆에서 띄우고 넘기기). 바꾸는 동안 그 앱은 503을 답한다. 그 자리에서 바꾸면 1 ms 남짓이다(기록의 + 모양이 바뀌는 큰 목록은 목록을 다시 쓰는 동안). - HTTP로 앱을 더하고 바꾸는 길. 경로의 인증(3b) 뒤에 따로 정한다. **3b: 경로의 인증.** 앱의 경로를 누가 부를 수 있는지다(CHECKPOINT의 남은 것). 3단계의 수명과 따로 설계한다. +### 3단계에서 알게 된 것 + +- **멈추고 다시 열면 다시 읽기가 전부였다.** 처음 구현(`12878cf`)은 바뀐 앱을 멈추고 저장소에서 다시 열었다. 항목 100만 개의 + 앱이 150.6 ms를 답하지 못해 호스트를 다시 띄우는 것(149.7 ms)과 같았다. 그 가운데 142 ms가 저장소를 다시 읽는 일이었다. + 저장소가 그대로인 앱을 그 자리에서 바꾸자(`7daf406`) 1.12 ms가 됐다(1,024개 1.06 ms). 기록의 모양이 바뀌는 모듈은 목록을 새 + 모양으로 다시 쓰느라 171.5 ms다(다시 띄우면 332 ms). +- **결과.** 한 앱을 거듭 바꾸는 동안 다른 앱의 p99는 0.97배, 앱 하나의 호스트는 TPC-C +0.7%와 명령 수 +0.02% 이하, 모듈을 바꿀 + 때마다 19 KB가 남는다. 파일을 읽는 스레드가 하나 늘었다(앱 100개에 스레드 넷). 커밋: Pure `14c75d0`(해석한 모듈과 앱의 자리), + `1d892e2`(링크 스트림의 입력을 다시 찾기), `12878cf`(SIGHUP과 멈추고 다시 열기), `7daf406`(그 자리에서 바꾸기), `f5e9db5`와 + 그 뒤(측정). +- **검사가 찾은 것.** 보내는 앱이 멈추는 동안 받는 앱의 차례가 놓인 출구를 읽던 자리, 시작하기 전의 앱의 락을 다른 앱의 출구가 + 쓰던 것. 둘 다 바꾸기 한가운데의 보내는 앱과 받는 앱을 함께 바꿔 보는 검사로 드러났다. + ## 3단계의 착수 기준 - **바꿀 결정:** 달리는 호스트의 앱을 SIGHUP과 구성 파일로 더하고, 멈추고, 바꿀지다. 아래를 채우지 못하면 앱을 바꿀 때 호스트를 |
