aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/design/029-past-one-node.md38
1 files changed, 37 insertions, 1 deletions
diff --git a/docs/design/029-past-one-node.md b/docs/design/029-past-one-node.md
index 93c2752..287fa64 100644
--- a/docs/design/029-past-one-node.md
+++ b/docs/design/029-past-one-node.md
@@ -6,7 +6,8 @@
**원리 1은 UAX #14에서 깨졌다(2026-10-19, 045).** 두 실험 모두 막대에 못 미쳤다. (가) 2.19배(막대 4배), (나) 1.31배(막대
3배). 아래 "깨는 실험의 결과"에 무엇을 시험했고 무엇은 시험하지 않았는지 적는다. 깨진 것은 "실행기의 몸을 이어 붙인다"는
길이다. 표현까지 증명에서 내보내는 것은 손으로 쓴 점에서 range() 하나가 C의 1.75배, UAX #14의 처리기 전체가 C의 2.5배였다
-(사건 자체의 1,566은 따로 남는다). 원리 2는 아직 시험하지 않았다.
+(사건 자체의 1,566은 따로 남는다). 원리 2는 깨는 실험을 지났다(046: 같음, 이어받기, 찢긴 꼬리). 다만 "구간"은
+"파일의 연산"이어야 했다.
## 쉬운 말로
@@ -18,6 +19,8 @@ pure link는 전송 세션이 들고 있던 것(순번, 확인, 다시 보내기
**이어 붙이는 길은 깨졌다(045).** range()에서 절벽은 수와 리스트의 표현(10.9배), 메모리의 칸과 부름(3.29배), 분배(1.78배)의
곱이었다.
- **원리 2.** 복제 프로토콜이 들고 다닐 것을 저장소의 커밋과 링크가 이미 들고 있다. 복제 계층이 사라진다.
+ **깨는 실험을 지났다(046).** 저장소가 제 sync에서 끊은 제 파일 연산을 pure link로 보내면, 따르는 노드의 파일이 바이트까지 같고
+ kill -9 뒤에 주인으로 열린다.
## 원리 1. 증명이 곧 컴파일러다
@@ -232,6 +235,39 @@ C의 속도로 컴파일하기 쉬운 쪽**이어야 한다. 61–183배의 절�
- 주인을 kill -9하고, 따르는 노드의 저장소를 주인으로 연다.
- 통과: 고른 모든 시점에 파일이 같고, heard가 덮은 저장의 사건이 모두 있다.
+**깨는 실험의 결과(2026-10-19, `research/experiments/046-commit-replica`).** 미리 정한 둘 다 지났다.
+- 장치. 주인(`pure-run --store`)에 `shim.so`를 미리 싣는다. shim은 주인의 저장소가 파일에 하는 일을 모두 연산으로 받는다(`ops.h`:
+ 만들기, 쓰기, 자르기, 자리 잡기, 이름 바꾸기, 지우기, 디렉터리 만들기). fsync나 fdatasync 하나가 컷 하나를 끝낸다. 컷은 pure link로
+ 따르는 노드에 가고(`shipper.c`, `follower.c`), 따르는 노드는 같은 연산을 제 디렉터리에서 차례대로 다시 한다. 주인의 sync는 따르는
+ 노드가 그 컷을 저장했다고 링크가 말한 뒤에야 돌아온다(동기). 그래서 날아가는 중인 컷은 하나뿐이고, 복제의 로그는 없다. 확인은
+ 링크의 heard다. 보내지 않는 길로 파일이 바뀌면(쓰기 가능한 공유 매핑, 복제한 기술자, 오프셋 없는 write) shim이 프로세스를 멈춘다.
+ 두 저장소는 /dev/shm에 있다. 시험하는 것은 같음과 이어받기이지 매체가 아니다.
+- **같음.** 메시지 10만 개(컷 200,081개, 압축 34번, 이미지 다시 쓰기 1번)와 20만 개(컷 400,149개, 압축 67번, 두 번째 로그 조각)에서,
+ 1,999컷과 3,001컷마다 주인을 멈추고 두 저장소를 이름과 바이트까지 견주었다. 표본 233번과 끝에서 다른 바이트는 0이다.
+- **이어받기.** kill -9를 70번 했다. 주인만 죽인 것, 기계째(shipper도) 죽인 것, 기계째에 컷을 512 B와 64 B 레코드로 쪼갠 것이다.
+ 따르는 노드의 저장소는 70번 모두 주인으로 열린다. 주인이 끝났다고 한 메시지를 모두 담고, 보내지 않은 것은 없고, 항목은 차례대로다.
+ 70번 모두 죽은 주인의 제 저장소와 같은 수를 담았다.
+- **찢긴 꼬리.** 컷의 레코드는 한 묶음으로 건너가서, kill이 컷의 중간을 남긴 일은 한 번도 없었다. 그래서 따르는 노드가 가질 수 있는
+ 상태를 직접 만들었다(`prefixes.py`). 메시지 10만 개의 연산 흐름(507,150개)에서 연산 경계 867곳까지 적용한 저장소를 주인으로 열었다.
+ 컷 안에서 끝나는 것이 568곳, 압축과 이미지 설치 둘레가 266곳이다. 모두 오류 없이 열리고, 담은 항목이 정확히 처음 메시지들의
+ 것이며, 짧은 접두가 담은 것을 긴 접두가 잃지 않는다.
+- **원리의 문구와 어긋난 것.** "저장 한 번이 쓰는 것은 모두 스스로 경계를 갖고 스스로 검증하는 구간"은 문구대로는 틀렸다. 저장소는
+ 구간 말고 파일의 연산도 한다. 꼬리에 0을 미리 쓰고, 압축한 새 트리를 프로세스 번호가 든 임시 이름으로 써서 rename으로 설치하고,
+ 이미지도 그렇게 설치하며, 디렉터리를 fsync하고, 로그 조각을 8 MB씩 잡는다. 그래서 구간이 아니라 연산 여덟 가지를 실었다. 029가
+ "첫 실증이 그것을 드러낸다"고 적은 것이 그것이다. 그래도 복제 계층은 없다. 실은 것은 저장소가 제 sync에서 끊은 제 연산이고,
+ 확인은 heard다.
+- **값.** /dev/shm에서 메시지 하나에 204 µs → 400 µs(두 번 재어 같다)다. 그 가운데 155 µs가 확인을 기다린 시간이다(메시지 하나에
+ 컷 둘). 보낸 바이트는 메시지 하나에 903 B다. 압축의 새 파일 371, 트리의 커밋 365, 로그 71, 이미지 7이다. 그 42%(3,800만 B)가
+ 미리 쓴 0이다. 0은 따르는 노드가 스스로 만들 수 있으니, 연산 하나("여기서부터 이만큼 0")로 보내면 반으로 준다. 재지 않았다.
+- **시험하지 않은 것.**
+ - 따르는 노드를 다시 시작하는 것. heard는 메모리에 있다. 계층을 지우는 다음 답은 heard를 따르는 노드의 파일(트리의 마지막 커밋)에서
+ 읽는 것이다. 트리의 머리가 늘기만 하는 커밋 번호를 갖는지 확인하지 않았다.
+ - `pure-serve`. 체크포인트를 다른 스레드가 쓴다. shim은 바꾸는 호출을 잠금 아래에서 하므로 차례는 지키지만, 돌려 보지 않았다.
+ - 참 매체(SD 카드의 fsync), 두 기계, 잃는 길. 여기서는 루프백이라 다시 보낸 것이 0이다.
+ - 옛 로그 조각 지우기(unlink). 20만 개에서도 일어나지 않았다.
+ - 비동기(RPO > 0)와 주인을 고르는 규칙(아래).
+ - 장치는 시스템 호출을 가로채는 shim이다. 제품이라면 저장소가 제 컷을 스스로 내보낸다.
+
**미룬 것.** 둘이 동시에 주인이 되지 않게, 어느 노드가 파일을 주인으로 열지 정하는 합의의 규칙이 필요하다. 여기서 설계하지
않는다. 실험이 지난 뒤의 다음 결정이다.