aboutsummaryrefslogtreecommitdiffstats
path: root/docs/research/048-immutable-read-write-overlap.md
blob: 469ef0d7816062ea7e1e2801f5a279fee7364390 (plain)
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
# 048 — 저장 쓰기 중에도 기존 문서를 읽는 선택형 호스트

[046](046-optional-async-document-http.md)의 선택형 HTTP 호스트는 파일 효과를
작업자 하나에 넘겨 이벤트 루프를 보호했다. 다만 쓰기가 `fsync`에서 멈추면 다른
문서 읽기도 그 작업자 뒤에서 대기했다. 저장소 코드를 확인하면 읽기는 파일 버전을
열어 불변 `mmap`으로 유지하고, 쓰기만 임시 파일 번호와 `.writer.lock`을 사용한다.
따라서 **읽기 작업자 하나와 쓰기 작업자 하나**를 두되, 기존의 쓰기 직렬화는
유지하는 경계가 가능하다.

선택형 `PURE_HTTP_ASYNC` 호스트에서 두 작업자는 입력 종류에 따라 공유된
최대 8개 작업 슬롯을 탐색한다. 각 작업자의 스택 크기는 128 KiB로 설정했다.
HTTP 연결과 `pure_runtime_complete()`는 기존처럼 소유 스레드에서 처리한다.
기본 코어·CLI·HTTP에는 이 작업자들이 링크되지 않는다. 새 앱 모델이나 공용
코어 연산은 추가하지 않았다.

[결정적 HTTP 검사](../../prototypes/connections/results/2026-09-24-async-read-write/gated.json)는
실제 CLI로 `gated=old` 버전 1을 만든 뒤, HTTP 수정 `oldafter`를 파일 동기화
직전에 멈춘다. 쓰기를 풀기 **전에** 같은 문서의 GET이 `old`, ETag `"1"`을
반환한다. 이때 잘못된 다른 HTTP 요청도 400으로 답하고, 쓰기를 기다린 연결은
기한에 닫힌다. 쓰기를 풀면 GET이 `oldafter`, ETag `"2"`를 반환한다. 종료 중인
별도 실행에서도 진행 중인 쓰기 완료를 기다리고 종료 시 보유 본문은 0 B다.
이 검사는 한 작업자로 모든 파일 효과를 실행하던 호스트에서는 통과하지 않는다.
[ASan·UBSan 실행](../../prototypes/connections/results/2026-09-24-async-read-write/sanitized.json)과
[기존 HTTP 정확성 전체 검사](../../prototypes/connections/results/2026-09-24-async-read-write/full-check.json)도
통과했다.

[서비스 작업 원자료](../../prototypes/connections/results/2026-09-24-async-read-write/service-scale.json)는
고정 정의·소스 정의·선택형 비동기 소스 정의로 각각 8 KiB 문서 1,024개를
만들고 8개 클라이언트가 4,096개 요청을 처리한 결과다. 세 호스트의 최종 문서
해시와 저장 파일 수가 같고, 모두 보유 본문 0 B로 종료했다. 이 실행의 비용은
다음과 같다.

| Linux AArch64 / GCC 14 | 기본 소스 HTTP | 선택형 읽기+쓰기 HTTP |
|---|---:|---:|
| 링크된 `text` | 43,778 B | 48,401 B |
| 서버 구조체 | 41,528 B | 43,320 B |
| 유휴 RSS | 1,520 KiB | 1,552 KiB |
| 피크 RSS | 1,696 KiB | 1,728 KiB |
| 유휴 가상주소 공간 | 2,464 KiB | 2,848 KiB |
| 피크 가상주소 공간 | 2,528 KiB | 2,928 KiB |
| 프로세스 스레드 | 1 | 3 |

선택형 호스트는 기본 호스트보다 코드 4,623 B, 구조체 1,792 B, 이 작업의
피크 RSS 32 KiB가 더 든다. [이전 단일 작업자 기록](046-optional-async-document-http.md)과
비교하면 `text` 504 B와 구조체 96 B가 늘었다. 두 128 KiB 스택은 코드 섹션
크기에 포함되지 않는다. [크기 상한](../../prototypes/connections/results/2026-09-24-async-read-write/profile.json)은
기존 선택형 48 KiB 상한을 올리지 않고 통과했다. `make check-release`에서도
기본 코어 `text` 5,932 B, 기본 소스 HTTP `text` 43,778 B를 유지했다.

이는 **느린 쓰기와 기존 버전 읽기의 독립성 및 스냅샷 정확성**에 대한 결과다.
읽기끼리, 쓰기끼리는 각각 직렬이며, 기한이 지난 쓰기도 취소되지 않고 커밋될
수 있다. 매핑되지 않은 파일 캐시와 커널 소켓 버퍼는 프로세스 RSS 표에 포함되지
않는다. 이 작업은 처리량이나
Kitex급 RPC 성능을 측정하지 않는다. 일반 네트워크·UI 효과까지 같은 완료 모델에
연결하려면 저장소형 `READ/WRITE/SPLICE` 계약에서 벗어나는 별도 설계와 앱 검증이
필요하다.