aboutsummaryrefslogtreecommitdiff
path: root/docs/history/36-alloc/notes.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/history/36-alloc/notes.md')
-rw-r--r--docs/history/36-alloc/notes.md47
1 files changed, 47 insertions, 0 deletions
diff --git a/docs/history/36-alloc/notes.md b/docs/history/36-alloc/notes.md
new file mode 100644
index 0000000..aff6965
--- /dev/null
+++ b/docs/history/36-alloc/notes.md
@@ -0,0 +1,47 @@
+# 36 — allocator
+
+the tree was paying for a quarantine and a sweep on every `new`. `free` left the block intact until `gc` walked the heap. a uniquely owned pointer does not need that. `free(d*x)`, and the free the analyzer emits when an owned local dies, now call `recycle`. children go first, then the block is pushed onto its size-class list. there is no buddy walk and no heap scan. a plain `free`, the one an alias might still see, still quarantines. `tests/quarantine.zc` is that contract, and it still prints `0 1234`.
+
+the header lost the class word. size is `p[-5]`, and the class sits in the high bits of the flags word, so `p[-4]` through `p[-1]` are still flags, check word, owner and type. a two-word node is still 8 words: five header words plus two payload words is 7, and the smallest block is 8. a three-word node fits in 8 instead of 16. `new(int)` therefore reports a payload of 3 in `memreport`, and `tests/memleak.zc` expects that. the slack past the size `new` was asked for is zeroed, so a later walk does not follow an uninitialized word. the words that were asked for stay uninitialized in `new_raw`.
+
+`arena_new(n)`, `arena_alloc` and `arena_reset` are a bump allocator over one owned block. the pointers it hands out are interior. resetting the bump reuses them. `tests/arena.zc` and `tests/recycle.zc` cover both.
+
+`<<` is an enhancement, and `heap_init` runs before the image installs enhancements, so the class is packed with a multiply by `pow2[16]` rather than a shift.
+
+the stage-0 image is 100933 words and the fixpoint is 105074. the small compiler's stage-0 image is 100932, so its reservation moved from 100352 to 102400. that machine is still 184320 words; the extra reservation came out of the data-stack slack. the run-only image of `tests/bytes.zc` is 15030 words, so that reservation moved from 14336 to 15600. the machine is still 36864 words.
+
+the suite is 422 passed, 0 failed: interpreter, microcore, soft-float, the small and run-only maps, both virt boards, the arm64 jit and llvm.
+
+## sieve
+
+the sieve does not allocate in the loop. it stayed inside the previous spread. milliseconds per count, median of five slopes. the before column is `history/35-bench`.
+
+| path | before | after |
+| --- | ---: | ---: |
+| gcc -O3 -march=native, word flags | 0.149 | 0.149 |
+| gcc -O3 -march=native -flto, byte flags | 0.081 | 0.081 |
+| zc interpreter, plain, bounds-checked | 214.3 | 214.2 |
+| zc interpreter, o3, bounds-checked | 22.92 | 22.89 |
+| zc interpreter, o3, raw pointer | 14.36 | 14.63 |
+| zc llvm, ZYHOT=1, o3 raw pointer | 0.219 | 0.233 |
+| zc llvm, ZYHOT=1, o3 bounds-checked | 0.640 | 0.626 |
+| zc arm64 jit, qemu-user, o3 raw pointer | 2.094 | 2.066 |
+
+## trees
+
+milliseconds per tree of depth 12. same kernels as stage 35. gcc on this run was 0.091 for malloc and 0.0143 for the arena.
+
+| path | before | after |
+| --- | ---: | ---: |
+| gcc -O3 -march=native, malloc | 0.092 | 0.091 |
+| gcc -O3 -march=native -flto, arena | 0.0144 | 0.0143 |
+| zc interpreter, plain new/free | 178.1 | 76.37 |
+| zc interpreter, o3 new/free | 269.4 | 175.3 |
+| zc interpreter, o3 arena | 2.108 | 2.111 |
+| zc llvm, ZYHOT=1, plain new/free | 13.69 | 6.91 |
+| zc llvm, ZYHOT=1, o3 new/free | 23.70 | 15.73 |
+| zc llvm, ZYHOT=1, o3 arena | 0.282 | 0.270 |
+| zc arm64 jit, qemu-user, plain new/free | 80.83 | 44.85 |
+| zc arm64 jit, qemu-user, o3 arena | 1.667 | 1.554 |
+
+plain `new` / `free` is about 2.3x faster on the interpreter (76 ms against 178) and about 2.0x on llvm (6.9 ms against 13.7). the arm64 jit under qemu dropped from 81 ms to 45 ms. llvm against gcc `malloc` is about 76x, down from about 150x. the arena rows did not move: that kernel never calls the allocator. the o3 tree is still slower than the plain one (175 ms against 76, and 15.7 ms against 6.9), because `fatten` and `own` are still calls on every child.