diff options
| author | eunhhu <[email protected]> | 2026-10-18 17:54:16 +0100 |
|---|---|---|
| committer | eunhhu <[email protected]> | 2026-10-18 17:54:16 +0100 |
| commit | 9f17dd667c3282aa28d6b3961eda28e592961478 (patch) | |
| tree | db954434bdfde3186a06192f1b7ae4e93c44453c | |
| parent | d5f0cac74721863a91b0a799256b62c0b7b2a3c1 (diff) | |
| download | pure-9f17dd667c3282aa28d6b3961eda28e592961478.tar.gz pure-9f17dd667c3282aa28d6b3961eda28e592961478.zip | |
Research 140, 027's stage 3 measured: a board of columns of cards of tags (aup's stored_nested) alike in memory and on a store restarting eight times, every step's fault, states and a view (2,400 snapshots, 54 restarts); killed at the tree's four stages and the log's two, all or nothing; replacement moving nested lists by name at depth; appending into a stored item's list costs about 170 ns an item it already holds (append_cost.c: 42 µs an add on average over the first 500, 738 µs over 8,000), building one by appends quadratic; instruction counts: the first commit's BFS +1.45% with batches and +1.68% without, from branches in the hot steps, gone with the load's internal ops (b29 against b27: BFS 0.000%/+0.034%, the others within 0.008%; the bank's queries -0.25% to +0.22%); what remains (a message's rows holding lists, a list field's .count in a fold, for over xs[i].f); 027's stage 3 as made (the representation chosen against the plan, its cost); 008's wording (kind 5 in images' headers alone); CHECKPOINT's direction row through stage 3
| -rw-r--r-- | CHECKPOINT.md | 2 | ||||
| -rw-r--r-- | docs/design/008-module-format.md | 3 | ||||
| -rw-r--r-- | docs/design/027-computation-core.md | 15 | ||||
| -rw-r--r-- | docs/research/140-spec-suite.md | 60 | ||||
| -rw-r--r-- | research/experiments/040-against-c/2026-10-18-counts-s28.jsonl | 4 | ||||
| -rw-r--r-- | research/experiments/040-against-c/2026-10-18-counts-s28b.jsonl | 4 | ||||
| -rw-r--r-- | research/experiments/040-against-c/2026-10-18-counts-s29.jsonl | 4 | ||||
| -rw-r--r-- | research/experiments/040-against-c/2026-10-18-counts-s29b.jsonl | 4 | ||||
| -rw-r--r-- | research/experiments/041-batches/2026-10-18-counts.jsonl | 30 | ||||
| -rw-r--r-- | research/experiments/044-specs/2026-10-18-stage3-append.jsonl | 5 | ||||
| -rw-r--r-- | research/experiments/044-specs/append_cost.c | 31 |
11 files changed, 160 insertions, 2 deletions
diff --git a/CHECKPOINT.md b/CHECKPOINT.md index dccb646..7e6b43c 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`로 거절한다. 반복 아래에 값을 둔 모듈이 검증을 지나 실행기를 죽이던 구멍도 찾아 막았다. 줄 수는 검사기만 파이썬 이하이고(80 대 90), SHA-256(42 대 28)과 트리(142 대 105)는 길다. 시간은 C의 40–159배이고 바이트를 다루는 일은 순수 파이썬과 비슷하거나 느리다(0.43–1.6배): 핵이 선 뒤 빠르게 할 과녁이다 | [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배): 핵이 선 뒤 빠르게 할 과녁이다 | [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는 소유자 하나가 diff --git a/docs/design/008-module-format.md b/docs/design/008-module-format.md index a23f140..223bc4f 100644 --- a/docs/design/008-module-format.md +++ b/docs/design/008-module-format.md @@ -33,7 +33,8 @@ v6에는 뒤에 **i64**가 더해졌다([016](016-bool-and-i64.md)의 2단계): - 칸의 값은 이벤트가 만든 리스트의 번호(0은 빈 리스트)다. 정수처럼 옮겨지고 ITEM_GET으로 읽힌다. 스택의 타입은 리스트이고, 그 레코드를 가진다. - 3단계부터 저장 상태와 transient의 리스트도 그런 레코드를 받는다. 메시지의 행은 받지 않고, 리스트 필드는 키가 되지 않는다. -- 이벤트를 넘어 사는 리스트(저장, transient)의 칸은 리스트 값을 그 항목들의 저장 형태로 담는다(칸의 종류 5, 바이트처럼). 항목마다 +- 이벤트를 넘어 사는 리스트(저장, transient)의 칸은 리스트 값을 그 항목들의 저장 형태로 담는다(바이트처럼 담고, 이미지 머리는 종류 5로 + 적는다). 그런 칸을 다루는 명령은 로드가 실행기만의 내부 명령으로 바꿔 쓴다(다른 명령의 걸음은 그대로 둔다). 항목마다 필드의 차례로, 수·bool·i64는 8바이트 little-endian, text와 리스트는 u32le 길이와 바이트(리스트는 다시 이 형태)다. - ITEM_GET은 그것을 이벤트의 리스트 하나로 읽어 그 번호를 놓는다(읽은 바이트를 이벤트의 몫에 센다). - LIST_APPEND·LIST_INSERT·ITEM_SET은 이벤트의 리스트를 그 형태로 써 넣는다. APPEND_IN은 읽고, 덧붙이고, 다시 쓴다. diff --git a/docs/design/027-computation-core.md b/docs/design/027-computation-core.md index 660fccf..09392f3 100644 --- a/docs/design/027-computation-core.md +++ b/docs/design/027-computation-core.md @@ -186,6 +186,21 @@ - **막대.** 메모리 앱과 수시로 재시작하는 저장 앱이 매 단계 비트까지 같다(지금의 대조를 중첩으로 넓힌다). 커밋의 모든 단계에서 죽여도 전부 아니면 없음이다. +**만듦(2026-10-18).** 결과는 140의 3단계절이다. +- **고른 표현.** 계획(중첩 리스트마다 경로로 이름 붙인 이미지와 로그)과 다르게 했다. + - 이벤트를 넘어 사는 리스트(저장, transient)의 칸이 리스트 값을 그 항목들의 저장 형태로 담는다(바이트처럼 담고, 이미지 머리는 종류 5로 적는다). + - 읽으면 이벤트의 리스트 하나로 풀리고(ITEM_GET), 쓰면 그것에서 지어진다. +- **그래서 따라오는 것.** 리스트 모듈은 그 칸을 text의 바이트처럼 다룬다. 그래서 이미 있는 기계가 깊이에서도 그대로다. + - 이미지, 로그, 되돌리기, 읽는 쪽과의 나눔이 그렇다. + - 커밋의 원자성과 죽음의 회복도 그렇다. 새 저장소 형식과 새 복구 길이 없다. +- **이름 잇기.** 이미지의 머리가 레코드 그래프를 적는다(레코드가 리스트를 거쳐 자신을 담을 수 있어서 트리가 아니라 번호로 가리키는 + 표다). 시작과 교체는 그래프를 따라 이름으로 옮긴다. +- **비용.** 중첩 리스트를 바꿀 때마다 그 값 전체를 풀고 짓고 쓴다. 바뀐 것이 아니라 그 값의 크기에 비례한다. + - 큰 중첩 리스트를 덧붙여 짓는 것은 제곱이다. + - 구조를 나누는 표현(노드를 나누는 트리, 경로로 이름 붙인 로그)은 뜻을 바꾸지 않고 나중에 고를 수 있는 구현이다. +- **남은 것.** 메시지의 행이 리스트를 담는 것(JSON 경계에서 바로 트리로)은 4단계다. 접기 안에서 리스트 필드의 `.count`를 읽는 것도 + 아직 안 된다(레지스터를 묶어야 해서). + ### 4단계: 패턴 모으기 - 앵커, 메시지 하나인 입력, 아무 값인 보기를 둔다. diff --git a/docs/research/140-spec-suite.md b/docs/research/140-spec-suite.md index 13d8849..44f4e9f 100644 --- a/docs/research/140-spec-suite.md +++ b/docs/research/140-spec-suite.md @@ -364,6 +364,66 @@ **2단계의 막대 전체.** JSON 파서가 `y_`를 모두 받고 `n_`을 모두 거절한다(지남). `i_`는 정한 쪽을 적었다. 줄 수는 못 미쳤다(위). 시간은 적었다. TPC-C의 모듈과 은행 질의의 명령 수는 그대로다(지남). +## 027의 3단계: 중첩한 저장 상태 (2026-10-18) + +3단계에서 더한 것: +- **Pure.** + - 저장 상태와 transient의 리스트가 리스트를 담은 레코드를 받는다. 메시지의 행은 아직 받지 않고, 리스트 필드는 키가 되지 않는다. + - 그런 칸은 리스트 값을 그 항목들의 저장 형태로 담는다. 항목마다 필드의 차례로, 수·bool·i64는 8바이트, text와 리스트는 u32le + 길이와 바이트(리스트는 다시 이 형태)다. + - ITEM_GET은 그것을 이벤트의 리스트 하나로 풀고(읽은 바이트를 이벤트의 몫에 센다), LIST_APPEND·LIST_INSERT·ITEM_SET은 이벤트의 + 리스트에서 짓는다. APPEND_IN은 풀고, 덧붙이고, 다시 쓴다(이벤트와 함께 되돌려진다). + - 이미지의 머리가 레코드 그래프를 적는다. 시작과 교체는 그래프를 따라 필드 이름으로 깊이까지 옮긴다. +- **aup.** + - 저장 항목의 리스트에 덧붙이기(`columns[i].cards.append(...)`), let의 리스트·`[]`·리스트 값을 필드에 쓰기 + - 같은 레코드의 항목을 그대로 덧붙이기(`ys.append(y)`) +- **그대로인 것.** 리스트 모듈은 그 칸을 text의 바이트처럼 다룬다. 그래서 이미지, 로그, 되돌리기, 읽는 쪽과의 나눔, 커밋의 원자성, + 죽음의 회복이 깊이에서도 그대로다. 새 저장소 형식도 새 복구 길도 없다. + +**맞음.** aup의 검사 `stored_nested`가 보드(열 → 카드 → 태그, 카드의 태그를 읽는 보기 하나)를 무작위 걸음으로 돌린다. +- 같은 걸음을 메모리 앱과 저장 앱에 준다. 저장 앱은 실행 하나에 여덟 번 재시작하고, 실행의 절반은 몰아서 저장한다. +- 씨앗 여섯, 걸음 200개다. 매 걸음의 실패, 상태, 보기가 모두 같다(스냅숏 2,400개, 재시작 54번). + +**죽음.** Pure의 단위 시험 `nested_crashes`가 중첩 리스트를 바꾸는 커밋의 도중에 프로세스를 죽인다. +- 트리의 네 단계와 로그의 두 단계에서 죽인다. 다시 열면 매번 그 커밋 전부이거나 아무것도 아니다. +- 실패한 커밋은 아무것도 바꾸지 않는다. + +**이름 잇기.** 단위 시험 `nested_replace`가 저장 리스트와 transient 리스트의 중첩 리스트를 교체로 옮긴다. +- 보드의 필드 차례가 바뀌고 잎의 레코드에 필드(`w = 7`)가 더해진다. 값은 이름으로 깊이까지 옮겨지고, 새 필드는 기본값을 받는다. +- 이 단위 시험들은 ASan·UBSan 빌드로도 지났다. + +**막대.** + +| 막대 | 잰 것 | | +|---|---|---| +| 메모리 대 재시작하는 저장 앱 | 매 걸음 같음(스냅숏 2,400개, 재시작 54번) | 지남 | +| 커밋의 모든 단계에서 죽임 | 여섯 단계 모두 전부 아니면 없음 | 지남 | +| 기존 일의 명령 수 | 아래(막대 1%) | 지남 | + +**비용.** 중첩 리스트를 바꿀 때마다 그 값 전체를 풀고 짓고 쓴다. 바뀐 크기가 아니라 그 값의 크기에 비례한다. +- 한 열에 카드를 하나씩 덧붙이면(메모리), 처음 n번의 덧붙이기 평균이 500에서 42 µs, 1,000에서 84 µs, 2,000에서 171 µs, 4,000에서 + 349 µs, 8,000에서 738 µs다. 덧붙이기 한 번이 이미 있는 카드 하나에 170 ns 남짓이다. 그래서 n개를 덧붙여 짓는 것은 제곱이다. +- 구조를 나누는 표현(노드를 나누는 트리, 경로로 이름 붙인 로그)은 뜻을 바꾸지 않고 나중에 고를 수 있는 구현이다(027). +- 원본: `research/experiments/044-specs/append_cost.c`, `2026-10-18-stage3-append.jsonl`. + +**기존 일의 명령 수(3단계).** +- 첫 커밋(d8e2974, b28)에서 BFS가 묶음 +1.45%, 실행기만 +1.68%로 막대를 넘었다. 나머지 넷은 ±0.01% 안이었다. + - 원인은 셋이었다. `pure_cell_text`의 비교가 늘었고, `text_field`가 리스트 필드를 알게 되었다(BFS의 덧붙이기마다 필드마다 두 번 + 묻는다). 셋째는 뜨거운 경우들 안의 새 갈래였다. + - 앞의 둘을 되돌리니 일부만 돌아왔다. 남은 것은 갈래가 `step`의 코드 생성을 옮긴 값이었다. +- 고친 커밋(d5f0cac, b29)은 그런 칸을 다루는 명령을 로드가 내부 명령(OP_KEPT_*)으로 바꿔 쓴다. 검증과 계획이 끝난 뒤에 바꾸므로 + 모듈은 그 명령을 담지 않는다. JIT는 그 블록을 실행기에 맡긴다. 그래서 다른 명령의 걸음은 3단계 전과 같다. +- b29 대 b27(2c): BFS 묶음 0.000%, 실행기만 +0.034%. join +0.008%, knapsack +0.001%, matmul +0.001%, roots 0.000%. +- 은행 질의(s27 대 s29, 각 네 번): per_branch −0.14%, in_credit −0.25%, large +0.12%, ranks −0.08%, none 0.00%, field +0.22%, + found +0.15%(막대 ±1%). +- 원본: `041-batches/2026-10-18-counts.jsonl`(b28, b29), `040-against-c/2026-10-18-counts-s28.jsonl`, `-s28b.jsonl`, `-s29.jsonl`, + `-s29b.jsonl`. + +**남은 것.** +- 메시지의 행이 리스트를 담는 것(JSON 경계에서 바로 트리로)은 4단계다. +- 접기 안에서 리스트 필드의 `.count`를 읽는 것(`sum(c.cards.count for c in cols)`)은 거절된다. 접기는 레지스터를 묶지 않기 때문이다. +- `for c in columns[i].cards`는 구문이 받지 않는다. `let col = columns[i]`로 한 번 거친다. + ## 착수 기준 (다음 일) - **바꿀 결정.** 계산의 핵을 설계한다(027). 위 표의 여덟 후보 가운데 무엇을 어떤 모양으로 받을지 정한다. diff --git a/research/experiments/040-against-c/2026-10-18-counts-s28.jsonl b/research/experiments/040-against-c/2026-10-18-counts-s28.jsonl new file mode 100644 index 0000000..9f15831 --- /dev/null +++ b/research/experiments/040-against-c/2026-10-18-counts-s28.jsonl @@ -0,0 +1,4 @@ +{"serve": "pure-serve", "per_branch": {"instructions": 26993254, "cycles": 11740994}, "in_credit": {"instructions": 3492731, "cycles": 1596075}, "large": {"instructions": 1421590, "cycles": 608185}, "ranks": {"instructions": 24405011, "cycles": 14759082}, "none": {"instructions": 617115, "cycles": 193288}, "field": {"instructions": 9008642, "cycles": 3329258}, "found": {"instructions": 14162159, "cycles": 10622538}} +{"serve": "pure-serve", "per_branch": {"instructions": 26913366, "cycles": 11814716}, "in_credit": {"instructions": 3469742, "cycles": 1611678}, "large": {"instructions": 1419483, "cycles": 613860}, "ranks": {"instructions": 24329541, "cycles": 14818502}, "none": {"instructions": 609616, "cycles": 192301}, "field": {"instructions": 9091175, "cycles": 3335693}, "found": {"instructions": 14192769, "cycles": 10584266}} +{"serve": "pure-serve", "per_branch": {"instructions": 27071550, "cycles": 11772202}, "in_credit": {"instructions": 3510278, "cycles": 1585989}, "large": {"instructions": 1421574, "cycles": 614859}, "ranks": {"instructions": 24447396, "cycles": 14867972}, "none": {"instructions": 617123, "cycles": 195315}, "field": {"instructions": 9008650, "cycles": 3335571}, "found": {"instructions": 14162088, "cycles": 10638817}} +{"serve": "pure-serve", "per_branch": {"instructions": 26862304, "cycles": 11837964}, "in_credit": {"instructions": 3458213, "cycles": 1582318}, "large": {"instructions": 1419531, "cycles": 610145}, "ranks": {"instructions": 24301257, "cycles": 14709708}, "none": {"instructions": 609627, "cycles": 191705}, "field": {"instructions": 9091183, "cycles": 3341920}, "found": {"instructions": 14193944, "cycles": 10536164}} diff --git a/research/experiments/040-against-c/2026-10-18-counts-s28b.jsonl b/research/experiments/040-against-c/2026-10-18-counts-s28b.jsonl new file mode 100644 index 0000000..c01bd1e --- /dev/null +++ b/research/experiments/040-against-c/2026-10-18-counts-s28b.jsonl @@ -0,0 +1,4 @@ +{"serve": "pure-serve", "per_branch": {"instructions": 27001538, "cycles": 11809316}, "in_credit": {"instructions": 3494481, "cycles": 1569742}, "large": {"instructions": 1421590, "cycles": 604735}, "ranks": {"instructions": 24408555, "cycles": 14810612}, "none": {"instructions": 617115, "cycles": 192941}, "field": {"instructions": 9008642, "cycles": 3329022}, "found": {"instructions": 14162664, "cycles": 11129426}} +{"serve": "pure-serve", "per_branch": {"instructions": 26948211, "cycles": 11936877}, "in_credit": {"instructions": 3477619, "cycles": 1611437}, "large": {"instructions": 1419539, "cycles": 610405}, "ranks": {"instructions": 24348016, "cycles": 14784698}, "none": {"instructions": 609616, "cycles": 191620}, "field": {"instructions": 9091175, "cycles": 3341083}, "found": {"instructions": 14194665, "cycles": 10446188}} +{"serve": "pure-serve", "per_branch": {"instructions": 26988888, "cycles": 11750407}, "in_credit": {"instructions": 3491586, "cycles": 1595540}, "large": {"instructions": 1421574, "cycles": 636840}, "ranks": {"instructions": 24400679, "cycles": 14772759}, "none": {"instructions": 617115, "cycles": 195556}, "field": {"instructions": 9008642, "cycles": 3347715}, "found": {"instructions": 14162495, "cycles": 10844953}} +{"serve": "pure-serve", "per_branch": {"instructions": 26996410, "cycles": 11973005}, "in_credit": {"instructions": 3488363, "cycles": 1620090}, "large": {"instructions": 1419507, "cycles": 608760}, "ranks": {"instructions": 24375152, "cycles": 14826597}, "none": {"instructions": 609616, "cycles": 195343}, "field": {"instructions": 9091175, "cycles": 3343996}, "found": {"instructions": 14193560, "cycles": 10567563}} diff --git a/research/experiments/040-against-c/2026-10-18-counts-s29.jsonl b/research/experiments/040-against-c/2026-10-18-counts-s29.jsonl new file mode 100644 index 0000000..81c9bd3 --- /dev/null +++ b/research/experiments/040-against-c/2026-10-18-counts-s29.jsonl @@ -0,0 +1,4 @@ +{"serve": "pure-serve", "per_branch": {"instructions": 27116137, "cycles": 11997606}, "in_credit": {"instructions": 3520317, "cycles": 1616754}, "large": {"instructions": 1421542, "cycles": 614630}, "ranks": {"instructions": 24471297, "cycles": 15007601}, "none": {"instructions": 617115, "cycles": 192792}, "field": {"instructions": 9008642, "cycles": 3337037}, "found": {"instructions": 14159784, "cycles": 10692334}} +{"serve": "pure-serve", "per_branch": {"instructions": 27056903, "cycles": 11835214}, "in_credit": {"instructions": 3506950, "cycles": 1611934}, "large": {"instructions": 1423230, "cycles": 606586}, "ranks": {"instructions": 24440693, "cycles": 14710399}, "none": {"instructions": 617123, "cycles": 188625}, "field": {"instructions": 9028796, "cycles": 3324917}, "found": {"instructions": 14181050, "cycles": 10573198}} +{"serve": "pure-serve", "per_branch": {"instructions": 27248168, "cycles": 11963826}, "in_credit": {"instructions": 3549879, "cycles": 1624579}, "large": {"instructions": 1421510, "cycles": 616012}, "ranks": {"instructions": 24543862, "cycles": 14971502}, "none": {"instructions": 617115, "cycles": 191202}, "field": {"instructions": 9008642, "cycles": 3311617}, "found": {"instructions": 14160408, "cycles": 10612142}} +{"serve": "pure-serve", "per_branch": {"instructions": 27123191, "cycles": 11920638}, "in_credit": {"instructions": 3522018, "cycles": 1662019}, "large": {"instructions": 1423174, "cycles": 607058}, "ranks": {"instructions": 24478800, "cycles": 14557857}, "none": {"instructions": 617115, "cycles": 191160}, "field": {"instructions": 9028788, "cycles": 3349276}, "found": {"instructions": 14179810, "cycles": 10480322}} diff --git a/research/experiments/040-against-c/2026-10-18-counts-s29b.jsonl b/research/experiments/040-against-c/2026-10-18-counts-s29b.jsonl new file mode 100644 index 0000000..a8e790f --- /dev/null +++ b/research/experiments/040-against-c/2026-10-18-counts-s29b.jsonl @@ -0,0 +1,4 @@ +{"serve": "pure-serve", "per_branch": {"instructions": 27029002, "cycles": 11776162}, "in_credit": {"instructions": 3500598, "cycles": 1592396}, "large": {"instructions": 1421494, "cycles": 616464}, "ranks": {"instructions": 24423096, "cycles": 14830472}, "none": {"instructions": 617115, "cycles": 193696}, "field": {"instructions": 9008642, "cycles": 3333335}, "found": {"instructions": 14160504, "cycles": 10573768}} +{"serve": "pure-serve", "per_branch": {"instructions": 26995382, "cycles": 11747780}, "in_credit": {"instructions": 3493042, "cycles": 1601323}, "large": {"instructions": 1423270, "cycles": 627277}, "ranks": {"instructions": 24406230, "cycles": 14860436}, "none": {"instructions": 617123, "cycles": 194410}, "field": {"instructions": 9028796, "cycles": 3475763}, "found": {"instructions": 14181649, "cycles": 10710498}} +{"serve": "pure-serve", "per_branch": {"instructions": 27093262, "cycles": 11829227}, "in_credit": {"instructions": 3515171, "cycles": 1600382}, "large": {"instructions": 1421478, "cycles": 605106}, "ranks": {"instructions": 24459441, "cycles": 14835459}, "none": {"instructions": 617123, "cycles": 205990}, "field": {"instructions": 9008650, "cycles": 3326333}, "found": {"instructions": 14158911, "cycles": 10562014}} +{"serve": "pure-serve", "per_branch": {"instructions": 27075692, "cycles": 12014054}, "in_credit": {"instructions": 3511134, "cycles": 1575796}, "large": {"instructions": 1423230, "cycles": 613250}, "ranks": {"instructions": 24450931, "cycles": 14811696}, "none": {"instructions": 617115, "cycles": 192768}, "field": {"instructions": 9028788, "cycles": 3337929}, "found": {"instructions": 14182210, "cycles": 10470045}} diff --git a/research/experiments/041-batches/2026-10-18-counts.jsonl b/research/experiments/041-batches/2026-10-18-counts.jsonl index d1f5c4d..6db0072 100644 --- a/research/experiments/041-batches/2026-10-18-counts.jsonl +++ b/research/experiments/041-batches/2026-10-18-counts.jsonl @@ -18,3 +18,33 @@ {"version":"b26","way":"rounds","work":"join","instructions":7659168467,"cycles":3373811804} {"version":"b26","way":"batches","work":"bfs","instructions":3371506688,"cycles":1643771467} {"version":"b26","way":"rounds","work":"bfs","instructions":4712039680,"cycles":2075728320} +{"version":"b28","way":"batches","work":"matmul","instructions":713412706,"cycles":228056209} +{"version":"b28","way":"rounds","work":"matmul","instructions":21223846502,"cycles":6836648106} +{"version":"b28","way":"batches","work":"knapsack","instructions":348670652,"cycles":105217756} +{"version":"b28","way":"rounds","work":"knapsack","instructions":22004470545,"cycles":7867695936} +{"version":"b28","way":"batches","work":"roots","instructions":157304315,"cycles":109581739} +{"version":"b28","way":"rounds","work":"roots","instructions":2720117105,"cycles":1008706879} +{"version":"b28","way":"batches","work":"join","instructions":1783743144,"cycles":1007421023} +{"version":"b28","way":"rounds","work":"join","instructions":7692773476,"cycles":3312488537} +{"version":"b28","way":"batches","work":"bfs","instructions":3413152566,"cycles":1688940338} +{"version":"b28","way":"rounds","work":"bfs","instructions":4801845652,"cycles":2100396423} +{"version":"b27","way":"batches","work":"matmul","instructions":713395345,"cycles":228780268} +{"version":"b27","way":"rounds","work":"matmul","instructions":21265005926,"cycles":7318530139} +{"version":"b27","way":"batches","work":"knapsack","instructions":348632551,"cycles":105762362} +{"version":"b27","way":"rounds","work":"knapsack","instructions":21881484253,"cycles":8123105399} +{"version":"b27","way":"batches","work":"roots","instructions":157304178,"cycles":109418657} +{"version":"b27","way":"rounds","work":"roots","instructions":2719816944,"cycles":1106892113} +{"version":"b27","way":"batches","work":"join","instructions":1783718313,"cycles":1008040915} +{"version":"b27","way":"rounds","work":"join","instructions":7669672155,"cycles":3455880586} +{"version":"b27","way":"batches","work":"bfs","instructions":3364522644,"cycles":1647535969} +{"version":"b27","way":"rounds","work":"bfs","instructions":4722342813,"cycles":2084692974} +{"version":"b29","way":"batches","work":"matmul","instructions":713395677,"cycles":232196096} +{"version":"b29","way":"rounds","work":"matmul","instructions":21265247905,"cycles":7417709517} +{"version":"b29","way":"batches","work":"knapsack","instructions":348634210,"cycles":104739014} +{"version":"b29","way":"rounds","work":"knapsack","instructions":21881636483,"cycles":8104673362} +{"version":"b29","way":"batches","work":"roots","instructions":157304837,"cycles":109524488} +{"version":"b29","way":"rounds","work":"roots","instructions":2719817906,"cycles":1110164822} +{"version":"b29","way":"batches","work":"join","instructions":1783720744,"cycles":1038646954} +{"version":"b29","way":"rounds","work":"join","instructions":7670274118,"cycles":3526186126} +{"version":"b29","way":"batches","work":"bfs","instructions":3364524544,"cycles":1644560620} +{"version":"b29","way":"rounds","work":"bfs","instructions":4723942606,"cycles":2096987224} diff --git a/research/experiments/044-specs/2026-10-18-stage3-append.jsonl b/research/experiments/044-specs/2026-10-18-stage3-append.jsonl new file mode 100644 index 0000000..cd60baf --- /dev/null +++ b/research/experiments/044-specs/2026-10-18-stage3-append.jsonl @@ -0,0 +1,5 @@ +{"cards":500,"ns_per_add_so_far":42451} +{"cards":1000,"ns_per_add_so_far":84048} +{"cards":2000,"ns_per_add_so_far":170537} +{"cards":4000,"ns_per_add_so_far":348505} +{"cards":8000,"ns_per_add_so_far":738448} diff --git a/research/experiments/044-specs/append_cost.c b/research/experiments/044-specs/append_cost.c new file mode 100644 index 0000000..a3ef0bb --- /dev/null +++ b/research/experiments/044-specs/append_cost.c @@ -0,0 +1,31 @@ +/* Research 140, design 027 stage 3: the cost of appending into a stored list's item's list (aup's check.py BOARD_SOURCE + * compiled, add_card into one column, in memory): ns an add, on average so far, as the list grows. + * cc -O2 -std=c17 -I../../../core append_cost.c ../../../build/libpure.a -lm -pthread -o append_cost + * ./append_cost board.pmod */ +#define _POSIX_C_SOURCE 200809L +#include "module.h" +#include <stdio.h> +#include <string.h> +#include <time.h> +static double now_ns(void) { struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); return t.tv_sec * 1e9 + t.tv_nsec; } +int main(int argc, char **argv) { + PureModule m; char error[160]; + if (pure_module_read(argv[1], &m, error, sizeof(error)) != PURE_OK) { fprintf(stderr, "%s\n", error); return 1; } + PureApp app; + if (pure_app_start(&app, &m, (PureData){0}) != PURE_OK) return 1; + int column = pure_module_input(&m, "add_column"), card = pure_module_input(&m, "add_card"); + pure_app_message(&app, (uint32_t)column, NULL, -1, (PureSpan){(const unsigned char *)"todo", 4}); + unsigned char payload[16]; + double zero = 0; + memcpy(payload, &zero, 8); + memcpy(payload + 8, "card0001", 8); + double start = now_ns(); + for (int n = 1; n <= 8000; ++n) { + if (pure_app_message(&app, (uint32_t)card, NULL, -1, (PureSpan){payload, 16}) != PURE_OK) { fprintf(stderr, "fail at %d\n", n); return 1; } + if (n == 500 || n == 1000 || n == 2000 || n == 4000 || n == 8000) { + double t = now_ns(); + printf("{\"cards\":%d,\"ns_per_add_so_far\":%.0f}\n", n, (t - start) / n); + } + } + return 0; +} |
