aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/module.c73
-rw-r--r--core/module.h76
-rw-r--r--core/test-module.c6
-rw-r--r--docs/design/027-computation-core.md21
-rw-r--r--research/experiments/040-against-c/2026-10-18-counts-s38.jsonl6
-rw-r--r--research/experiments/041-batches/2026-10-18-counts.jsonl10
-rw-r--r--research/experiments/044-specs/append_cost.c2
-rw-r--r--research/experiments/044-specs/json_rec_time.c2
-rw-r--r--research/experiments/044-specs/json_time.c2
-rw-r--r--research/experiments/044-specs/json_tree_time.c2
-rw-r--r--research/experiments/044-specs/time.c2
11 files changed, 156 insertions, 46 deletions
diff --git a/core/module.c b/core/module.c
index e7118f0..f388ae7 100644
--- a/core/module.c
+++ b/core/module.c
@@ -1563,7 +1563,59 @@ PURE_COLD PureResult pure_module_read(const char *path, PureModule *out, char *e
return result;
}
+#ifdef __SANITIZE_ADDRESS__
+#include <sanitizer/asan_interface.h>
+enum { TABLE_GAP = 16 }; /* poisoned between tables: reading past one is caught */
+#else
+enum { TABLE_GAP = 0 };
+#endif
+
+/* The module's tables laid out from base (027's 4f-1), each a run of its entries aligned to 8; the bytes they take. */
+static size_t lay_tables(PureModule *m, uintptr_t base, size_t views, size_t signatures) {
+ size_t at = 0;
+#define LAY(member, count) \
+ (m->member = (void *)(base + at), at += (((size_t)(count) * sizeof(*m->member) + 7) & ~(size_t)7) + TABLE_GAP)
+ LAY(state_names, m->states), LAY(state_type, m->states), LAY(state_ref, m->states), LAY(state_flags, m->states);
+ LAY(state_key, m->states), LAY(state_indexed, m->states), LAY(initial, m->states);
+ LAY(input_names, m->inputs), LAY(input_keys, m->inputs), LAY(input, m->inputs), LAY(field, m->fields);
+ LAY(view_names, views), LAY(view_type, views), LAY(view_table, views), LAY(view_list, views), LAY(view_record, views);
+ LAY(view_field, views), LAY(view_computed, views), LAY(view_code, views), LAY(view_plan, views);
+ LAY(view_arguments, views), LAY(view_body, views), LAY(view_lists, views), LAY(view_range, views);
+ LAY(handler, m->handlers);
+ LAY(record_names, m->records), LAY(record, m->records), LAY(record_nested, m->records), LAY(record_held, m->records);
+ LAY(record_field_names, m->record_fields), LAY(record_field_type, m->record_fields);
+ LAY(record_field_default, m->record_fields);
+ LAY(function, m->functions), LAY(signature_type, signatures), LAY(signature_record, signatures);
+#undef LAY
+ return at;
+}
+
+static bool make_tables(PureModule *m, size_t views, size_t signatures) {
+ size_t size = lay_tables(m, 0, views, signatures);
+ unsigned char *base = calloc(1, size ? size : 1);
+ if (!base) return false;
+ m->tables = base;
+ lay_tables(m, (uintptr_t)base, views, signatures);
+#ifdef __SANITIZE_ADDRESS__
+ for (size_t at = 0; at + TABLE_GAP <= size;) { /* each run's gap, found again as it was laid out */
+ unsigned char *next = base + size;
+#define GAP(member) if ((unsigned char *)m->member > base + at && (unsigned char *)m->member < next) next = (unsigned char *)m->member;
+ GAP(state_type) GAP(state_ref) GAP(state_flags) GAP(state_key) GAP(state_indexed) GAP(initial) GAP(input_names)
+ GAP(input_keys) GAP(input) GAP(field) GAP(view_names) GAP(view_type) GAP(view_table) GAP(view_list) GAP(view_record)
+ GAP(view_field) GAP(view_computed) GAP(view_code) GAP(view_plan) GAP(view_arguments) GAP(view_body) GAP(view_lists)
+ GAP(view_range) GAP(handler) GAP(record_names) GAP(record) GAP(record_nested) GAP(record_held) GAP(record_field_names)
+ GAP(record_field_type) GAP(record_field_default) GAP(function) GAP(signature_type) GAP(signature_record)
+#undef GAP
+ ASAN_POISON_MEMORY_REGION(next - TABLE_GAP, TABLE_GAP);
+ at = (size_t)(next - base);
+ }
+#endif
+ return true;
+}
+
void pure_module_release(PureModule *m) {
+ free(m->tables);
+ m->tables = NULL;
pure_jit_free(m->jit);
m->jit = NULL;
m->batches = m->calls = false;
@@ -1664,6 +1716,23 @@ PURE_COLD PureResult pure_module_load(const void *bytes, size_t size, PureModule
out->constant_offset = (uint32_t *)(out->code + out->code_count);
out->constant_length = out->constant_offset + out->constants;
out->constant_data = (unsigned char *)(out->constant_length + out->constants);
+ /* Its tables, the columns the load makes among the views (027's 4e: a record's fields for each list view of a
+ * record), counted from the bytes first. */
+ size_t records_at = functions_at - (size_t)out->views * VIEW_BYTES - (size_t)out->handlers * HANDLER_BYTES -
+ (size_t)out->record_fields * RECORD_FIELD_BYTES - (size_t)out->records * RECORD_BYTES;
+ size_t made = 0, views_at = records_at + (size_t)out->records * RECORD_BYTES + (size_t)out->record_fields * RECORD_FIELD_BYTES;
+ for (uint32_t i = 0; i < out->views; ++i) {
+ const unsigned char *v = p + views_at + (size_t)i * VIEW_BYTES;
+ uint32_t record = read16(v + 8);
+ if (v[4] == PURE_VIEW_LIST && !read16(v + 6) && record && record <= out->records)
+ made += read16(p + records_at + (size_t)(record - 1) * RECORD_BYTES + 6);
+ }
+ if (out->views + made > PURE_MODULE_VIEWS) REFUSE("views and their columns", out->views);
+ size_t capacity = out->views + made;
+ if (!make_tables(out, capacity, signatures)) {
+ result = PURE_ALLOCATION;
+ REFUSE("out of memory", 0);
+ }
const unsigned char *at = p + PURE_MODULE_HEADER;
const unsigned char *text = p + size - constant_bytes - strings;
if (constant_bytes) memcpy(out->constant_data, p + size - constant_bytes, constant_bytes);
@@ -1879,7 +1948,7 @@ PURE_COLD PureResult pure_module_load(const void *bytes, size_t size, PureModule
if (!list_view(out, i) || !out->view_record[i]) continue;
const PureRecord *r = &out->record[out->view_record[i] - 1];
for (unsigned f = 0; f < r->count; ++f) {
- if (out->views == PURE_MODULE_VIEWS) REFUSE("views and their columns", i);
+ if (out->views == capacity) REFUSE("views and their columns", i);
uint32_t c = out->views++, field = r->first + f;
memcpy(out->view_names[c], out->record_field_names[field], PURE_MODULE_NAME);
out->view_type[c] = out->record_field_type[field];
@@ -2130,7 +2199,7 @@ refused:
#undef REFUSE
}
-static int find(const char (*names)[PURE_MODULE_NAME], unsigned count, const char *name) {
+static int find(char (*names)[PURE_MODULE_NAME], unsigned count, const char *name) {
for (unsigned i = 0; i < count; ++i)
if (!strcmp(names[i], name)) return (int)i;
return -1;
diff --git a/core/module.h b/core/module.h
index 20e5fba..8ea0574 100644
--- a/core/module.h
+++ b/core/module.h
@@ -367,18 +367,22 @@ _Static_assert(PURE_MODULE_STATES <= 32, "a state is a bit of PureApp.counted");
typedef struct {
uint16_t states, inputs, views, handlers, fields, constants, records, record_fields;
uint32_t code_count;
- char state_names[PURE_MODULE_STATES][PURE_MODULE_NAME];
- char input_names[PURE_MODULE_INPUTS][PURE_MODULE_NAME];
- char view_names[PURE_MODULE_VIEWS][PURE_MODULE_NAME];
- char input_keys[PURE_MODULE_INPUTS][PURE_MODULE_NAME];
- uint8_t state_type[PURE_MODULE_STATES];
- uint16_t state_ref[PURE_MODULE_STATES]; /* text: constant; cursor: text; list: record; index: list */
- uint8_t state_flags[PURE_MODULE_STATES]; /* cursor: PURE_CURSOR_STAYS; list: PURE_LIST_ROWS >> 8 */
+ /* Its tables (027's 4f-1), each sized to it in one block (tables) that load takes and pure_module_release gives
+ * back: a state's, an input's, a message field's, a view's (the columns the load makes among them), a handler's, a
+ * record's, a record field's, a function's and a signature item's entries. */
+ void *tables;
+ char (*state_names)[PURE_MODULE_NAME];
+ char (*input_names)[PURE_MODULE_NAME];
+ char (*view_names)[PURE_MODULE_NAME];
+ char (*input_keys)[PURE_MODULE_NAME];
+ uint8_t *state_type;
+ uint16_t *state_ref; /* text: constant; cursor: text; list: record; index: list */
+ uint8_t *state_flags; /* cursor: PURE_CURSOR_STAYS; list: PURE_LIST_ROWS >> 8 */
uint32_t transient; /* a bit per transient state */
/* A keyed list: its key field + 1 (0: none). Its items stay in key order
* (numbers by value, texts by bytes), each key once, and keys do not change. */
- uint8_t state_key[PURE_MODULE_STATES];
- bool state_indexed[PURE_MODULE_STATES]; /* list: an index state refers to it (set at load) */
+ uint8_t *state_key;
+ bool *state_indexed; /* list: an index state refers to it (set at load) */
uint8_t *height; /* the operand stack's height at each instruction, from its block's start (the verifier's) */
/* In a batch's block (module-batch.c), a value computed again by the same code as an earlier one whose operands
* nothing changed between: at its code's first instruction, the earlier root + 1 and its code's length (reuse_from,
@@ -391,45 +395,45 @@ typedef struct {
bool batches; /* a loop of it is planned to run in batches (module-batch.c, docs/design/024) */
uint8_t runner; /* which executor runs its blocks: 0 run's own steps, 1 with batches, 2 with calls (module.c) */
bool held; /* it holds bytes or texts by name (BYTES_STORE): events and views empty them as they begin */
- PureInputShape input[PURE_MODULE_INPUTS];
- PureField field[PURE_MODULE_FIELDS];
- PureValue initial[PURE_MODULE_STATES];
- uint8_t view_type[PURE_MODULE_VIEWS];
- uint16_t view_table[PURE_MODULE_VIEWS]; /* a column's list view + 1, or 0 */
- uint16_t view_list[PURE_MODULE_VIEWS]; /* the list state of a list view over one, or its column's */
- uint16_t view_record[PURE_MODULE_VIEWS]; /* a list view's or a list column's items' record + 1 (a map's: 0) */
- uint8_t view_field[PURE_MODULE_VIEWS]; /* a column the load made: its item's field + 1 (read as it is), or 0 */
- bool view_computed[PURE_MODULE_VIEWS]; /* a list view whose code leaves its list (a column's: its view's) */
- PureBlock view_code[PURE_MODULE_VIEWS];
- uint8_t view_plan[PURE_MODULE_VIEWS]; /* a table's filter runs a leaf of its list at once (as a fold may) */
- uint8_t view_arguments[PURE_MODULE_VIEWS]; /* the input of a view's arguments + 1 (a column's: its table's), or 0 */
+ PureInputShape *input;
+ PureField *field;
+ PureValue *initial;
+ uint8_t *view_type;
+ uint16_t *view_table; /* a column's list view + 1, or 0 */
+ uint16_t *view_list; /* the list state of a list view over one, or its column's */
+ uint16_t *view_record; /* a list view's or a list column's items' record + 1 (a map's: 0) */
+ uint8_t *view_field; /* a column the load made: its item's field + 1 (read as it is), or 0 */
+ bool *view_computed; /* a list view whose code leaves its list (a column's: its view's) */
+ PureBlock *view_code;
+ uint8_t *view_plan; /* a table's filter runs a leaf of its list at once (as a fold may) */
+ uint8_t *view_arguments; /* the input of a view's arguments + 1 (a column's: its table's), or 0 */
/* Set at load: a view's code computes (its locals and loops: a body), and the event's lists it changes, a bit each. */
- bool view_body[PURE_MODULE_VIEWS];
- uint32_t view_lists[PURE_MODULE_VIEWS];
+ bool *view_body;
+ uint32_t *view_lists;
PureShape shape[PURE_MODULE_SHAPES];
uint8_t shapes;
PureRange range[PURE_MODULE_RANGES];
uint8_t ranges;
- uint8_t view_range[PURE_MODULE_VIEWS]; /* a table's filter's PureRange + 1, or 0 */
- PureHandler handler[PURE_MODULE_HANDLERS];
+ uint8_t *view_range; /* a table's filter's PureRange + 1, or 0 */
+ PureHandler *handler;
/* The code and the text constants, sized to the module in one block
* (storage) that load takes and pure_module_release gives back. */
PureOp *code;
uint32_t *constant_offset, *constant_length;
unsigned char *constant_data;
void *storage;
- char record_names[PURE_MODULE_RECORDS][PURE_MODULE_NAME];
- PureRecord record[PURE_MODULE_RECORDS];
- char record_field_names[PURE_MODULE_RECORD_FIELDS][PURE_MODULE_NAME];
- uint8_t record_field_type[PURE_MODULE_RECORD_FIELDS]; /* PureRecordType */
- PureValue record_field_default[PURE_MODULE_RECORD_FIELDS]; /* a number (a bool's 0 or 1), an i64, a text constant's index
- * or a list's record (LIST, its i64) */
- bool record_nested[PURE_MODULE_RECORDS]; /* a record with a LIST field (set at load) */
- uint16_t record_held[PURE_MODULE_RECORDS]; /* its fields held as bytes are (pure_record_bytes), a bit each (set at load) */
+ char (*record_names)[PURE_MODULE_NAME];
+ PureRecord *record;
+ char (*record_field_names)[PURE_MODULE_NAME];
+ uint8_t *record_field_type; /* PureRecordType */
+ PureValue *record_field_default; /* a number (a bool's 0 or 1), an i64, a text constant's index or a list's record
+ * (LIST, its i64) */
+ bool *record_nested; /* a record with a LIST field (set at load) */
+ uint16_t *record_held; /* its fields held as bytes are (pure_record_bytes), a bit each (set at load) */
uint16_t functions;
- PureFunction function[PURE_MODULE_FUNCTIONS];
- uint8_t signature_type[PURE_MODULE_SIGNATURES];
- uint16_t signature_record[PURE_MODULE_SIGNATURES];
+ PureFunction *function;
+ uint8_t *signature_type;
+ uint16_t *signature_record;
bool calls; /* it has functions: its blocks run in the executor that calls (module.c) */
} PureModule;
diff --git a/core/test-module.c b/core/test-module.c
index 8950018..8014d63 100644
--- a/core/test-module.c
+++ b/core/test-module.c
@@ -3483,7 +3483,7 @@ static void lane_folds(void) {
module_b.code[i].plan = module_b.code[i].shape = 0;
}
planned += module_a.view_plan[VIEWS];
- memset(module_b.view_plan, 0, sizeof(module_b.view_plan));
+ memset(module_b.view_plan, 0, module_b.views * sizeof(*module_b.view_plan));
pure_jit_free(module_b.jit); /* its code changed: compiled again (021) */
module_b.jit = pure_jit_make(&module_b);
PureApp a, b;
@@ -4079,7 +4079,7 @@ static void ranges(void) {
!module_a.code[45].range && module_a.view_range[6] && module_a.code[78].range && !module_a.code[102].range &&
!module_a.code[118].range && module_a.code[118].plan);
for (uint32_t i = 0; i < module_b.code_count; ++i) module_b.code[i].range = 0;
- memset(module_b.view_range, 0, sizeof(module_b.view_range));
+ memset(module_b.view_range, 0, module_b.views * sizeof(*module_b.view_range));
pure_jit_free(module_b.jit); /* its code changed: compiled again (021) */
module_b.jit = pure_jit_make(&module_b);
uint32_t seed = 0x7a45e11u;
@@ -5426,7 +5426,7 @@ static void output_meaning(void) {
NULL, 0};
Spec none = {nums, 1, none_inputs, 1, NULL, 0, none_handlers, 1, none_code, 2, NULL, 0, NULL, 0, NULL, 0, NULL, 0,
NULL, 0, NULL, 0};
- PureModule without;
+ PureModule without = {0};
CHECK(load(was, &module_a) == PURE_OK && load(now, &module_b) == PURE_OK && load(none, &without) == PURE_OK);
CHECK(pure_module_shape(&module_a, 1) != pure_module_shape(&module_b, 1));
char *path = new_store();
diff --git a/docs/design/027-computation-core.md b/docs/design/027-computation-core.md
index 16cb149..5951f1f 100644
--- a/docs/design/027-computation-core.md
+++ b/docs/design/027-computation-core.md
@@ -414,6 +414,27 @@
- 상태, 입력, 레코드, 필드, 중첩의 수를 모듈에 맞춰 잡는다. 비트 하나씩 쓰던 집합은 길이를 가진다.
- aup 소스의 32 KB도 뺀다.
- 앞의 걸음들이 표를 바꾸므로 마지막에 한다.
+ - **설계(2026-10-18).** 뜻에 남는 것은 예산(실행량, 메모리)과 형식의 너비(머리말의 u16 수, 명령의 인자)다. 구현은 표를 모듈에
+ 맞춰 잡고, 빠른 길이 작은 모듈에만 맞는 곳(JIT가 리스트를 32개까지 비트로 세는 것 따위)은 그 길의 조건으로 남긴다(넘으면 실행기).
+ 네 걸음으로 하고, 걸음마다 시험과 명령 수의 막대를 지킨다:
+ - 4f-1: 모듈의 표를 모듈에 맞춰 잡는다. `PureModule`의 고정 배열(상태, 입력, 보기, 핸들러, 메시지 필드, 레코드, 레코드 필드,
+ 함수, 서명)이 로드가 머리말의 수(와 지은 열)로 잡는 한 블록을 가리킨다. 쓰는 곳의 모양(`m->state_type[i]`)은 그대로이고,
+ 한도는 아직 그대로다. 표현만 바뀐다.
+ - 4f-2: 상태 32를 뺀다. 상태의 비트 집합(transient, 앱이 세는 상태, 보기와 함수가 바꾸는 리스트, 걷는 리스트)은 상태마다의
+ 표시나 길이를 가진 목록이 된다. 앱의 상태마다의 배열(값, text, 리스트, 읽는 쪽의 리스트)과 스냅숏의 것도 모듈에 맞춰 잡고,
+ 이벤트와 보기가 값을 베끼던 스택의 32칸은 앱의 칸이 된다.
+ - 4f-3: 입력 32, 레코드 16, 레코드의 필드 16, 보기 64, 핸들러 64, 메시지 필드 64를 뺀다. 항목의 칸을 담던 스택의 16칸은 모듈의
+ 가장 큰 레코드에 맞춘 앱의 칸이 되고, 레코드마다의 비트 집합(바이트로 담는 필드)은 필드마다의 표시가 된다. 호스트(serve의
+ 타이머, Vega의 타이머)의 입력마다의 배열도 모듈에 맞춘다.
+ - 4f-4: 반복의 겹 8을 뺀다(실행기의 겹 칸이 자란다). aup의 소스 32 KB와 aup 안의 같은 한도들(상태, 입력, 레코드, 필드,
+ 보기, 핸들러)을 뺀다.
+ - **4f-1 만듦(2026-10-18).** `PureModule`의 표 서른넷이 로드가 잡는 한 블록(`tables`)의 자리를 가리킨다(`lay_tables`가 머리말의 수와
+ 지을 열의 수로 놓는다. 지을 열은 보기 항목과 레코드 항목의 바이트에서 먼저 센다). sanitizer 빌드는 표 사이에 독을 둔 16바이트를
+ 두어, 한 표를 넘어 읽는 것을 잡는다(시험에서 걸린 것은 없다). `PureModule`은 24,320바이트에서 2,752바이트가 되었다(코어 22,383 → 22,456줄). 시험 하나와
+ 연구의 측정 다섯이 0으로 채우지 않은 모듈을 로드에 넘겼다(로드는 전의 것을 돌려주므로 0이어야 한다). 이제 0으로 시작한다.
+ - 명령 수(b38 대 b37): 묶음과 함께 BFS −0.24%, matmul −0.21%, 나머지 ±0.1% 안이다. 실행기만은 matmul −0.45%, join +0.36%,
+ knapsack +0.28%, BFS −0.25%, roots 0.00%다. 은행 질의(s37과 s38, 같은 aup 모듈을 한 번에 번갈아 세 번의 중앙값)는 field −0.68%,
+ found −0.51%, large −0.47%, none −0.20%, in_credit −0.19%, ranks −0.12%, per_branch −0.11%다.
- **차례의 까닭.**
- 4a는 작고, 3단계의 끝을 맺는다.
- 4b는 가장 많이 지운다. 키 있는 메시지와 기준 리비전이 사라지면 4d가 단순해진다.
diff --git a/research/experiments/040-against-c/2026-10-18-counts-s38.jsonl b/research/experiments/040-against-c/2026-10-18-counts-s38.jsonl
new file mode 100644
index 0000000..1f42341
--- /dev/null
+++ b/research/experiments/040-against-c/2026-10-18-counts-s38.jsonl
@@ -0,0 +1,6 @@
+{"serve": "pure-serve", "per_branch": {"instructions": 26882993, "cycles": 11591444}, "in_credit": {"instructions": 3463530, "cycles": 1578356}, "large": {"instructions": 1431957, "cycles": 606184}, "ranks": {"instructions": 24353508, "cycles": 14592354}, "none": {"instructions": 617958, "cycles": 194299}, "field": {"instructions": 9130366, "cycles": 3276393}, "found": {"instructions": 14283102, "cycles": 10549487}}
+{"serve": "pure-serve", "per_branch": {"instructions": 26981160, "cycles": 11735192}, "in_credit": {"instructions": 3485848, "cycles": 1600650}, "large": {"instructions": 1425150, "cycles": 615394}, "ranks": {"instructions": 24395965, "cycles": 14718379}, "none": {"instructions": 616741, "cycles": 192127}, "field": {"instructions": 9068166, "cycles": 3309134}, "found": {"instructions": 14210927, "cycles": 10867715}}
+{"serve": "pure-serve", "per_branch": {"instructions": 27279333, "cycles": 11875510}, "in_credit": {"instructions": 3552478, "cycles": 1606311}, "large": {"instructions": 1431845, "cycles": 608216}, "ranks": {"instructions": 24571658, "cycles": 14808241}, "none": {"instructions": 617958, "cycles": 190338}, "field": {"instructions": 9130469, "cycles": 3268205}, "found": {"instructions": 14280287, "cycles": 10521880}}
+{"serve": "pure-serve", "per_branch": {"instructions": 27199381, "cycles": 11813156}, "in_credit": {"instructions": 3534764, "cycles": 1608765}, "large": {"instructions": 1425086, "cycles": 608142}, "ranks": {"instructions": 24516404, "cycles": 14877701}, "none": {"instructions": 616741, "cycles": 190908}, "field": {"instructions": 9068063, "cycles": 3313632}, "found": {"instructions": 14207590, "cycles": 10633858}}
+{"serve": "pure-serve", "per_branch": {"instructions": 27230259, "cycles": 11911492}, "in_credit": {"instructions": 3541457, "cycles": 1606705}, "large": {"instructions": 1431789, "cycles": 602954}, "ranks": {"instructions": 24545122, "cycles": 14981424}, "none": {"instructions": 617950, "cycles": 191656}, "field": {"instructions": 9130358, "cycles": 3268257}, "found": {"instructions": 14279831, "cycles": 10508190}}
+{"serve": "pure-serve", "per_branch": {"instructions": 27329624, "cycles": 12359635}, "in_credit": {"instructions": 3563802, "cycles": 2339609}, "large": {"instructions": 1425094, "cycles": 749512}, "ranks": {"instructions": 24586049, "cycles": 15314398}, "none": {"instructions": 616733, "cycles": 190282}, "field": {"instructions": 9068158, "cycles": 3309742}, "found": {"instructions": 14207319, "cycles": 10912495}}
diff --git a/research/experiments/041-batches/2026-10-18-counts.jsonl b/research/experiments/041-batches/2026-10-18-counts.jsonl
index f493618..7b29e36 100644
--- a/research/experiments/041-batches/2026-10-18-counts.jsonl
+++ b/research/experiments/041-batches/2026-10-18-counts.jsonl
@@ -128,3 +128,13 @@
{"version":"b37","way":"rounds","work":"matmul","instructions":21259969629,"cycles":6204053361}
{"version":"b37","way":"batches","work":"bfs","instructions":3347488616,"cycles":1663777730}
{"version":"b37","way":"rounds","work":"bfs","instructions":4709044317,"cycles":2143909347}
+{"version":"b38","way":"batches","work":"roots","instructions":157248661,"cycles":109895799}
+{"version":"b38","way":"rounds","work":"roots","instructions":2719817740,"cycles":1102038842}
+{"version":"b38","way":"batches","work":"knapsack","instructions":348023990,"cycles":106312579}
+{"version":"b38","way":"rounds","work":"knapsack","instructions":22053584918,"cycles":8200983416}
+{"version":"b38","way":"batches","work":"join","instructions":1783615210,"cycles":1338885351}
+{"version":"b38","way":"rounds","work":"join","instructions":7705975089,"cycles":4071828568}
+{"version":"b38","way":"batches","work":"matmul","instructions":702228751,"cycles":227165183}
+{"version":"b38","way":"rounds","work":"matmul","instructions":21163848735,"cycles":7467484636}
+{"version":"b38","way":"batches","work":"bfs","instructions":3339436314,"cycles":1648001735}
+{"version":"b38","way":"rounds","work":"bfs","instructions":4697444852,"cycles":2103018632}
diff --git a/research/experiments/044-specs/append_cost.c b/research/experiments/044-specs/append_cost.c
index a3ef0bb..d91e82e 100644
--- a/research/experiments/044-specs/append_cost.c
+++ b/research/experiments/044-specs/append_cost.c
@@ -9,7 +9,7 @@
#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];
+ PureModule m = {0}; 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;
diff --git a/research/experiments/044-specs/json_rec_time.c b/research/experiments/044-specs/json_rec_time.c
index 03c02c4..0d5b225 100644
--- a/research/experiments/044-specs/json_rec_time.c
+++ b/research/experiments/044-specs/json_rec_time.c
@@ -73,7 +73,7 @@ int main(int argc, char **argv) {
n += (size_t)sprintf(doc + n, "%s{\"key%d\": [1.5e3, true, null, \"text \\u00e9 %d\"]}", k ? "," : "", k, k);
doc[n++] = ']';
doc[n] = 0;
- PureModule module;
+ PureModule module = {0};
char error[160];
if (pure_module_read(argv[1], &module, error, sizeof(error)) != PURE_OK) { fprintf(stderr, "%s\n", error); return 1; }
PureApp app;
diff --git a/research/experiments/044-specs/json_time.c b/research/experiments/044-specs/json_time.c
index b401ece..b4b2eae 100644
--- a/research/experiments/044-specs/json_time.c
+++ b/research/experiments/044-specs/json_time.c
@@ -100,7 +100,7 @@ int main(int argc, char **argv) {
for (int k = 0; k < 2000; ++k)
n += (size_t)sprintf((char *)doc + n, "%s{\"key%d\": [1.5e3, true, null, \"text \\u00e9 %d\"]}", k ? "," : "", k, k);
doc[n++] = ']';
- PureModule module;
+ PureModule module = {0};
char error[160];
if (pure_module_read(argv[1], &module, error, sizeof(error)) != PURE_OK) { fprintf(stderr, "%s\n", error); return 1; }
PureApp app;
diff --git a/research/experiments/044-specs/json_tree_time.c b/research/experiments/044-specs/json_tree_time.c
index 1cac21a..0ec4bec 100644
--- a/research/experiments/044-specs/json_tree_time.c
+++ b/research/experiments/044-specs/json_tree_time.c
@@ -73,7 +73,7 @@ int main(int argc, char **argv) {
n += (size_t)sprintf(doc + n, "%s{\"key%d\": [1.5e3, true, null, \"text \\u00e9 %d\"]}", k ? "," : "", k, k);
doc[n++] = ']';
doc[n] = 0;
- PureModule module;
+ PureModule module = {0};
char error[160];
if (pure_module_read(argv[1], &module, error, sizeof(error)) != PURE_OK) { fprintf(stderr, "%s\n", error); return 1; }
PureApp app;
diff --git a/research/experiments/044-specs/time.c b/research/experiments/044-specs/time.c
index 248889b..f296ece 100644
--- a/research/experiments/044-specs/time.c
+++ b/research/experiments/044-specs/time.c
@@ -83,7 +83,7 @@ int main(int argc, char **argv) {
uint32_t seed = 140;
for (size_t i = 0; i < size; ++i) seed = seed * 1664525u + 1013904223u, data[i] = (unsigned char)(seed >> 24);
- PureModule module;
+ PureModule module = {0};
char error[160];
if (pure_module_read(argv[1], &module, error, sizeof(error)) != PURE_OK) { fprintf(stderr, "%s\n", error); return 1; }
PureApp app;