From e64b609d1f3b6ef314002156f3b882e10650f9fb Mon Sep 17 00:00:00 2001 From: eunhhu Date: Mon, 19 Oct 2026 08:21:45 +0100 Subject: CHECKPOINT: the gaps to 1.0 as they stand after 027 and 140 (the contract's rebuild left: the core's three gaps, the one-shot timer and lending list values as decision points, the work unit, the fixed limits, no frozen spec; byte and text work 61-186x C; aup 1.47-2.04x Python's lines; three machines last seen together 10-05; one entry point, packages, hosts beyond Linux, a C ABI; the evidence table still the document app's); the direction row's frictions and list values --- CHECKPOINT.md | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/CHECKPOINT.md b/CHECKPOINT.md index 050931b..309f35c 100644 --- a/CHECKPOINT.md +++ b/CHECKPOINT.md @@ -26,7 +26,7 @@ | 표 크기의 상태 | 목록이 영속 B+트리다(변경·키 탐색·저장본 위치 O(log n), 스냅숏 O(1), 1,600만 항목, 런타임 상태 1 GiB). pgbench의 TPC-B 같은 이체(세 표의 행과 이력, 한 트랜잭션)가 10만 계좌에서 RAM 24.5k/s(전: 3만 계좌 3.2k/s), SD 카드 내구 1,339/s(SQLite WAL FULL 84–153/s) | [090](docs/research/090-tables.md) | | 일반 트랜잭션 | TPC-C의 다섯 트랜잭션을 aup 앱 하나로 쓴다(여러 표 읽기·쓰기, 조각 훑기, 중복 없는 셈, 실패하면 통째 되돌림). 같은 입력에서 SQLite와 아홉 표의 모든 행이 같다(창고 하나와 넷). RAM 초당 40,976건(W=4 35,838; 조율한 SQLite 10,164, 트랜잭션당 CPU 43–50 µs, HTTP·JSON 포함), SD 카드 내구 4,980건(W=4 4,590). SQLite도 카드에 맞게 조율하고 묶어 커밋하면 739건(W=4 426)이다. 남은 차이는 거래당 쓰는 바이트다(SQLite는 페이지째 써서 8–18배) | [092](docs/research/092-tpcc.md), [106](docs/research/106-tpcc-conditions-first.md), [107](docs/research/107-snapshot-nodes-reused.md) | | 질의 | 질의는 앱의 상태 위에 보기를 더한 모듈이다(`aup query`, `PUT·GET /queries/이름`). 검증한 뒤 스냅숏에서 돌고, 열 안의 fold가 그 행을 읽는다(상관 부질의). 잎이 항목을 필드별로 들고, fold와 필터는 잎 하나씩 돌며(결함이 날 잎만 항목별로), 열 안의 그룹·순위 fold는 목록을 한 번 지나 모든 행에 답한다. 10만 계좌에서 지점별 합계 4.9 ms(SQLite 45, 인덱스를 주면 14.3), 조인 0.48 ms(1.47), 자기 조인 순위 6.8 ms(2,840, 인덱스를 주면 7.6). Pure에는 인덱스 선언이 없다 | [091](docs/research/091-queries.md) | -| 방향(1.0 전) | 앱 계약을 1.0에서 얼릴 후보로 적었다: 이벤트는 전함수이고 원자적이며 결정적이다, 시간은 입력이다, 보기는 커밋된 상태의 순수 함수다, 보이는 역사는 커밋의 앞부분이다, 전달은 순서대로 한 번이다. 계산의 언어(명령 90개, 상태 종류 7개)는 패턴의 모음이라 다시 세운다. 분야마다 고른 명세 열한 개의 묶음에서 오늘의 aup는 바이트, 비트 연산, 중첩, 재귀, 갈래, 글자 읽기에 막힌다(탐침 열 개). 1.0 전에는 호환을 챙기지 않고, JSON과 HTTP는 경계에 남는다. 계산의 핵을 다섯 단계로 다시 세운다(027). 1단계(비트 연산, 자리의 바이트, 수의 리스트, 한 번에 주기)로 aup로 쓴 SHA-256이 공식 벡터를 세 실행 길에서 모두 지난다. 2a(형식 지정, 바이트 잇기와 자르기, 바이트와 text의 let, `while`, 단락 평가의 `&&`·`||`)로 쓴 JSON 검사기가 JSONTestSuite에서 하나도 틀리지 않는다. 2b(레코드 안의 레코드, 갈래와 `match`, 레코드 안의 리스트, 수 읽기)로 JSON을 트리로 읽어 다이제스트가 파이썬과 같다(JSONTestSuite, 무작위 문서 300개). 2c(스스로 부르는 함수: 부름마다 제 스택·지역 칸·리스트·레지스터·담은 값, 깊이는 표로 센 프레임 바이트가 몫에서 묶음; 값으로서의 레코드; 글자 읽기)로 JSON 트리를 재귀 하강으로 다시 써 JSONTestSuite와 무작위 문서 300개가 파이썬과 같고, 10만 겹은 `memory`로 거절한다. 반복 아래에 값을 둔 모듈이 검증을 지나 실행기를 죽이던 구멍도 찾아 막았다. 3단계(중첩한 저장 상태: 저장과 transient의 리스트가 리스트를 담은 레코드를 받고, 그 칸은 값을 항목들의 저장 형태로 바이트처럼 담아 이미지·로그·되돌리기·회복이 그대로다)로 열 → 카드 → 태그의 보드가 메모리 앱과 여덟 번 재시작하는 저장 앱에서 매 걸음 같고(스냅숏 2,400개), 커밋의 여섯 단계 어디서 죽여도 전부 아니면 없음이며, 교체는 이름으로 깊이까지 옮긴다. 중첩 리스트를 바꾸는 비용은 그 값의 크기에 비례한다(이미 있는 항목 하나에 170 ns). 줄 수는 검사기만 파이썬 이하이고(80 대 90), SHA-256(42 대 28)과 트리(142 대 105)는 길다. 시간은 C의 40–159배이고 바이트를 다루는 일은 순수 파이썬과 비슷하거나 느리다(0.43–1.6배): 핵이 선 뒤 빠르게 할 과녁이다. 4단계(패턴 모으기)로 메시지의 행이 중첩을 받고, 키별 문서가 키 있는 리스트에 녹고, 커서와 인덱스가 앵커 하나가 되고, 키·text·타이머·프레임·가리킴이 묶인 메시지가 되고, 보기가 아무 값(리스트 보기: 상태 그대로, 걸러짐, 지도, 본문이 지은 리스트; 바이트)이 되고, 고정 한도가 형식과 리스트 엔진의 너비만 남았다: 명령 106 → 95, 상태 종류 7 → 6, 입력 종류 6 → 3, 그동안 다섯 일의 명령 수와 은행 질의는 걸음마다 1% 안, TPC-C는 3단계 끝과 같다(+0.37%). 5단계(수의 모델: number는 binary64로 리터럴과 셈의 기본, i64는 정확한 정수·비트·돈, `/`와 내림한 몫 `//`, i64의 합은 정확하게, 돈은 i64의 센트로 `.2d`에 보이고, 교체는 정확할 때만 옮긴다)로 TPC-C의 돈과 비율이 Pure와 SQLite 모두에서 정수가 되어, 2만 트랜잭션 뒤 모든 행이 오차 없이 같다: 명령 95 → 96, 다섯 일의 명령 수와 은행 질의는 4단계 끝과 1% 안, TPC-C는 런타임이 같고(−0.03%) i64의 돈으로 앱이 2.6% 빠르다. 027의 다섯 단계를 마쳤다. 그 뒤 묶음의 3(inflate)을 새 명령 없이 썼다: zlib가 만든 스트림 640개와 손상된 240개가 파이썬 참조와 같지만, 우회가 셋(리스트를 받지 않는 fn, 바이트 하나인 상태, 블록 안의 리스트)이고 줄은 파이썬의 1.6배, 시간은 같은 알고리즘의 C의 108배다. 묶음의 1(DNS 메시지)도 새 명령 없이 썼다: dnspython이 만든 메시지 400개를 읽고 다시 써 dnspython이 같게 읽고, 손상된 300개가 파이썬 참조와 같다. 우회는 둘(바이트의 `==`, 보기에서 부르는 블록 fn)이고 둘 다 핵의 일이며, 줄은 파이썬의 1.6배, 시간은 C의 67배(파이썬보다 1.9배 느림)다. 묶음의 9(HTTP/1.1 요청을 패킷마다)도 새 명령 없이 썼다: 스트림 200개를 어디서 잘라도 h11과 같다. 이로써 바이트 하나인 상태와 바이트의 `==`는 써서 닿은 명세가 둘이 되어 핵에 들일 자격이 생겼다(140의 결정점). 그 둘을 핵에 들였다: 바이트의 비교(TEXT_COMPARE의 비트)와 바이트 하나인 상태(028, `values`의 표시로 손상과 옮김을 가른다). aup에는 맨 리스트의 인자와 결과, 블록 안의 let 리스트를 더했다(작은 블록 fn의 인라인은 만들어 쟀으나 효과가 없어 넣지 않았다). 세 명세의 우회를 걷어 내니 줄이 파이썬의 1.5–1.9배가 되었고, DNS는 명령이 21% 줄었다. 묶음의 5(UAX #14 줄 나누기)를 데이터를 입력으로 받아 썼다: LineBreakTest.txt 16,672줄 모두와 무작위 2,000줄이 세 길에서 맞고, 시간은 Vega의 C의 199배다. 묶음의 10(RFC 6298 재전송 타이머)을 주기 틱으로 썼다: 사건 241,612개가 같은 규칙의 모델과 같고, 10 ms 틱이면 타임아웃 하나에 틱이 2,796개 든다. 단발 타이머는 명세 하나만 닿아 적어 두고 만들지 않았다. 묶음의 8(상자 배치)을 Flexbox의 부분집합(한 줄, 9.7의 고정 고리까지, 내용 크기 없이)으로 썼다: 무작위 트리 2,000개가 Taffy와 0.01 안, 파이썬 참조와 비트까지 같고, 시간은 Taffy의 7.4배다. 쓰는 동안 aup가 메시지의 행을 위치로 읽을 때마다 행 전체를 복사하던 것을 찾아 고쳤다(노드당 99,067 → 4,737 ns) | [026](docs/design/026-app-contract.md), [027](docs/design/027-computation-core.md), [140](docs/research/140-spec-suite.md) | +| 방향(1.0 전) | 앱 계약을 1.0에서 얼릴 후보로 적었다: 이벤트는 전함수이고 원자적이며 결정적이다, 시간은 입력이다, 보기는 커밋된 상태의 순수 함수다, 보이는 역사는 커밋의 앞부분이다, 전달은 순서대로 한 번이다. 계산의 언어(명령 90개, 상태 종류 7개)는 패턴의 모음이라 다시 세운다. 분야마다 고른 명세 열한 개의 묶음에서 오늘의 aup는 바이트, 비트 연산, 중첩, 재귀, 갈래, 글자 읽기에 막힌다(탐침 열 개). 1.0 전에는 호환을 챙기지 않고, JSON과 HTTP는 경계에 남는다. 계산의 핵을 다섯 단계로 다시 세운다(027). 1단계(비트 연산, 자리의 바이트, 수의 리스트, 한 번에 주기)로 aup로 쓴 SHA-256이 공식 벡터를 세 실행 길에서 모두 지난다. 2a(형식 지정, 바이트 잇기와 자르기, 바이트와 text의 let, `while`, 단락 평가의 `&&`·`||`)로 쓴 JSON 검사기가 JSONTestSuite에서 하나도 틀리지 않는다. 2b(레코드 안의 레코드, 갈래와 `match`, 레코드 안의 리스트, 수 읽기)로 JSON을 트리로 읽어 다이제스트가 파이썬과 같다(JSONTestSuite, 무작위 문서 300개). 2c(스스로 부르는 함수: 부름마다 제 스택·지역 칸·리스트·레지스터·담은 값, 깊이는 표로 센 프레임 바이트가 몫에서 묶음; 값으로서의 레코드; 글자 읽기)로 JSON 트리를 재귀 하강으로 다시 써 JSONTestSuite와 무작위 문서 300개가 파이썬과 같고, 10만 겹은 `memory`로 거절한다. 반복 아래에 값을 둔 모듈이 검증을 지나 실행기를 죽이던 구멍도 찾아 막았다. 3단계(중첩한 저장 상태: 저장과 transient의 리스트가 리스트를 담은 레코드를 받고, 그 칸은 값을 항목들의 저장 형태로 바이트처럼 담아 이미지·로그·되돌리기·회복이 그대로다)로 열 → 카드 → 태그의 보드가 메모리 앱과 여덟 번 재시작하는 저장 앱에서 매 걸음 같고(스냅숏 2,400개), 커밋의 여섯 단계 어디서 죽여도 전부 아니면 없음이며, 교체는 이름으로 깊이까지 옮긴다. 중첩 리스트를 바꾸는 비용은 그 값의 크기에 비례한다(이미 있는 항목 하나에 170 ns). 줄 수는 검사기만 파이썬 이하이고(80 대 90), SHA-256(42 대 28)과 트리(142 대 105)는 길다. 시간은 C의 40–159배이고 바이트를 다루는 일은 순수 파이썬과 비슷하거나 느리다(0.43–1.6배): 핵이 선 뒤 빠르게 할 과녁이다. 4단계(패턴 모으기)로 메시지의 행이 중첩을 받고, 키별 문서가 키 있는 리스트에 녹고, 커서와 인덱스가 앵커 하나가 되고, 키·text·타이머·프레임·가리킴이 묶인 메시지가 되고, 보기가 아무 값(리스트 보기: 상태 그대로, 걸러짐, 지도, 본문이 지은 리스트; 바이트)이 되고, 고정 한도가 형식과 리스트 엔진의 너비만 남았다: 명령 106 → 95, 상태 종류 7 → 6, 입력 종류 6 → 3, 그동안 다섯 일의 명령 수와 은행 질의는 걸음마다 1% 안, TPC-C는 3단계 끝과 같다(+0.37%). 5단계(수의 모델: number는 binary64로 리터럴과 셈의 기본, i64는 정확한 정수·비트·돈, `/`와 내림한 몫 `//`, i64의 합은 정확하게, 돈은 i64의 센트로 `.2d`에 보이고, 교체는 정확할 때만 옮긴다)로 TPC-C의 돈과 비율이 Pure와 SQLite 모두에서 정수가 되어, 2만 트랜잭션 뒤 모든 행이 오차 없이 같다: 명령 95 → 96, 다섯 일의 명령 수와 은행 질의는 4단계 끝과 1% 안, TPC-C는 런타임이 같고(−0.03%) i64의 돈으로 앱이 2.6% 빠르다. 027의 다섯 단계를 마쳤다. 그 뒤 묶음의 3(inflate)을 새 명령 없이 썼다: zlib가 만든 스트림 640개와 손상된 240개가 파이썬 참조와 같지만, 우회가 셋(리스트를 받지 않는 fn, 바이트 하나인 상태, 블록 안의 리스트)이고 줄은 파이썬의 1.6배, 시간은 같은 알고리즘의 C의 108배다. 묶음의 1(DNS 메시지)도 새 명령 없이 썼다: dnspython이 만든 메시지 400개를 읽고 다시 써 dnspython이 같게 읽고, 손상된 300개가 파이썬 참조와 같다. 우회는 둘(바이트의 `==`, 보기에서 부르는 블록 fn)이고 둘 다 핵의 일이며, 줄은 파이썬의 1.6배, 시간은 C의 67배(파이썬보다 1.9배 느림)다. 묶음의 9(HTTP/1.1 요청을 패킷마다)도 새 명령 없이 썼다: 스트림 200개를 어디서 잘라도 h11과 같다. 이로써 바이트 하나인 상태와 바이트의 `==`는 써서 닿은 명세가 둘이 되어 핵에 들일 자격이 생겼다(140의 결정점). 그 둘을 핵에 들였다: 바이트의 비교(TEXT_COMPARE의 비트)와 바이트 하나인 상태(028, `values`의 표시로 손상과 옮김을 가른다). aup에는 맨 리스트의 인자와 결과, 블록 안의 let 리스트를 더했다(작은 블록 fn의 인라인은 만들어 쟀으나 효과가 없어 넣지 않았다). 세 명세의 우회를 걷어 내니 줄이 파이썬의 1.5–1.9배가 되었고, DNS는 명령이 21% 줄었다. 묶음의 5(UAX #14 줄 나누기)를 데이터를 입력으로 받아 썼다: LineBreakTest.txt 16,672줄 모두와 무작위 2,000줄이 세 길에서 맞고, 시간은 Vega의 C의 199배다. 묶음의 10(RFC 6298 재전송 타이머)을 주기 틱으로 썼다: 사건 241,612개가 같은 규칙의 모델과 같고, 10 ms 틱이면 타임아웃 하나에 틱이 2,796개 든다. 단발 타이머는 명세 하나만 닿아 적어 두고 만들지 않았다. 묶음의 8(상자 배치)을 Flexbox의 부분집합(한 줄, 9.7의 고정 고리까지, 내용 크기 없이)으로 썼다: 무작위 트리 2,000개가 Taffy와 0.01 안, 파이썬 참조와 비트까지 같고, 시간은 Taffy의 7.4배다. 쓰는 동안 aup가 메시지의 행을 위치로 읽을 때마다 행 전체를 복사하던 것을 찾아 고쳤다(노드당 99,067 → 4,737 ns). 그 뒤 코어를 바꾸지 않고 aup의 마찰 일곱 가지를 걷어 냈다(리스트의 let 여럿, 대상 여럿, 리스트 값의 대입, `abs`, `tick.period`, 수를 만나는 16진): 줄은 파이썬의 1.47–2.04배이고 명령은 0.2% 안이다. 리스트 값은 설계부터 다시 보고, 수의 리스트를 배열째 복사하게만 했다(UAX #14 −6.8%; 빌려주고 떼기는 결정점). 1.0까지의 격차는 아래 "1.0까지 남은 격차"에 적었다 | [026](docs/design/026-app-contract.md), [027](docs/design/027-computation-core.md), [140](docs/research/140-spec-suite.md) | 키로 나눈 소유자와 저장을 넘길 스레드는 하지 않기로 했다. 이 장치는 동기화를 한 줄로 세워, 나누면 쓰기가 23% 줄고 넘겨도 기기의 일은 줄지 않는다([084](docs/research/084-parallel-syncs.md)). 다만 동기화가 공짜인 RAM에서 TPC-C는 소유자 하나가 @@ -39,6 +39,46 @@ 라우트의 TLS(앞단이 한다; 문서 피어의 TLS는 있다), HTTP로 앱을 더하고 바꾸는 길, aup·Vega의 배포 묶음, 캐시보다 큰 목록을 찾는 걸음(109: 미리 가져오기로는 줄지 않았다. 한 사건의 조회를 겹치거나 구조를 바꿔야 한다). +## 1.0까지 남은 격차 (2026-10-19) + +027의 다섯 단계와 140의 명세 열한 개(11의 암호는 설계상 aup 밖)를 마친 상태에서, 1.0(앱 계약을 얼리고 묶음을 내는 것)까지 남은 +것을 근거와 함께 가른다. + +**계약을 얼리기 전에(026의 "다시 세울 것").** +- **핵의 틈 셋([140](docs/research/140-spec-suite.md)).** 보기에서 블록 fn이나 재귀 fn을 부르기(검증기가 CALL을 핸들러에만 + 허락한다), 레코드나 갈래 하나인 상태, 커서 자리의 글자다. 쌓임을 막는 규칙(두 명세가 필요로 할 때)대로 아직 하나씩만 닿는다. + DNS가 첫째에 닿는다. +- **결정점 둘.** 단발 타이머는 RFC 6298 하나만 닿는다(10 ms 틱이면 타임아웃 하나에 틱 2,796개). 리스트 값을 빌려주고 떼기(복사를 + 0으로)는 남은 몫이 UAX #14 약 3%, JSON 트리 약 6%다. +- **예산의 단위.** 실행량은 블록을 쓴 대로 센다. 갈래가 어느 쪽으로 가든 같다(RFC 6298의 쉬는 틱과 만료한 틱이 같은 25). 이것을 + 계약의 단위로 얼릴지 정해야 한다. +- **고정 한도.** 레코드 16필드, 모듈의 fn 64개, 매개변수 8개, 핸들러의 let 64개, for 8겹, 식의 스택 64, 모듈 65,535명령이다. + 026은 1.0 전에 다시 세울 것으로 적었다. +- **계약의 글.** 026은 얼릴 후보 여덟 문장의 설계다. 모듈 형식 v7, 검증기의 불변식, 앱 계약을 한 판으로 얼린 명세는 아직 없다. + +**계산의 값(027: C에 가깝게).** +- 일곱 일은 C의 1.19–5.58배다(125). 바이트와 글자의 일은 실행기로 돌아 멀다: inflate 102배, DNS 61배, HTTP/1.1 83배, UAX #14 + 186배(6,445 대 34.7 ns), 상자 배치는 Taffy의 7.4배. 묶음 실행기와 기계어는 이 꼴을 빠르게 하지 못한다(140). +- 기계어를 걷어 낼지(바깥 피드백 006)는 아직이다. BFS(7.7 대 23.2 ms)와 matmul(14.2 대 25.8)에서 기계어가 앞선다(138). + +**쓰기의 값.** aup는 파이썬의 1.47–2.04배 줄이다(140, 마찰을 걷어 낸 뒤). 남은 것은 닫는 괄호의 줄, 레코드의 선언, 바이트마다 +도는 고리다. + +**기계와 플랫폼.** +- 세 기계의 확인은 10-05가 마지막이다(114, `pure-run` 1,053번). 027·028·140 뒤로는 Pi의 gcc와 clang이 같음만 봤다(486번, + 140). Mac과 WSL2는 이번에 닿지 않았다. clang 빌드가 027의 4f-2부터 서지 않던 것을 고쳤다. +- 호스트(`pure-serve`)와 링크는 리눅스에만 있다. macOS 지원을 주장하지 않는다. + +**묶음과 쓰는 길(위의 "남은 것", 바깥 피드백 006).** +- 진입점이 하나가 아니다. aup는 `check`, `build`, `watch`, `query`다. `aup run`도, 런타임을 담은 단일 실행 파일도 없다. + `pure-run`은 시험용이고(제품 인터페이스가 아니다), 운영은 `pure-serve`다. +- 그 밖에 남은 것: aup와 Vega의 배포 묶음, HTTP로 앱을 더하고 바꾸는 길, 앱 라우트의 TLS(앞단이 한다), 바뀐 모듈 놓기(교체마다 + 19 KB), 압축 없는 제자리 재사용 저장소, 응답을 기다리는 출력의 묶음 전달, 캐시보다 큰 목록 찾기. +- 다른 언어에서 부를 안정된 C ABI와 바인딩이 없다. `core/module.h`가 C에서 쓰는 길이고, 140의 시간 도구가 그것을 쓴다. + +**공개의 증거.** 아래 "공개할 작업물과 완료 증거" 표는 aup 이전의 문서 앱을 기준으로 적었다. 1.0의 증거 앱(Vega의 메신저, +TPC-C, 140의 명세 앱)으로 다시 써야 한다. 그 표의 미완료(실서비스 상호운용성, macOS 통과)는 그대로다. + ## 공개할 작업물과 완료 증거 기존 작업물 편집·저장 흐름을 발전시킨 **네이티브 작업물 편집기**를 하나의 검증 앱으로 삼는다. -- cgit v1.2.3