Skip to content

runtime: 帧级 ByRef 缓存,帧退出失效(#268) - #302

Open
carsontung666 wants to merge 4 commits into
array2d:masterfrom
carsontung666:feat/issue-268-handle-cache
Open

runtime: 帧级 ByRef 缓存,帧退出失效(#268)#302
carsontung666 wants to merge 4 commits into
array2d:masterfrom
carsontung666:feat/issue-268-handle-cache

Conversation

@carsontung666

@carsontung666 carsontung666 commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

叶子 block_id 几乎打不中,改成缓存 ART 父节点,同一帧/同一张表的兄弟 key 共用。帧退出失效,不穿透 Ptr。

配合:

runtime 侧相对上一版:

  • kvspaceRef_t rr = {0},避免 kvspace-c 只写前 8 字节时把栈垃圾当父节点 → SIGSEGV
  • 嵌套 key 首次 ResolveRef 后若 parent_id == 0,永久关闭父缓存(叶子/hot 仍可用)
  • macOS:weak_import + -Wl,-undefined,dynamic_lookup

benchmark 请用当前 master 做基线,并给「同树关缓存」对照;上一版描述里的 iops/prime_sieve/hash_table 数字相对 v0.2.17,与当前 master 不可比。

@carsontung666
carsontung666 force-pushed the feat/issue-268-handle-cache branch 4 times, most recently from 733855d to 8dd90aa Compare September 13, 2026 09:05
iops N=2000        26.3ms → 23.0ms  (−13%)
prime_sieve N=100  29.6ms → 26.8ms  (−9%)
hash_table N=200   18.0ms → 15.6ms  (−13%)
@carsontung666
carsontung666 force-pushed the feat/issue-268-handle-cache branch from 8dd90aa to 613ba14 Compare September 13, 2026 09:28
@miaobyte

Copy link
Copy Markdown
Contributor

本地复核:三仓 PR 组合 · 干净重编 · benchmark

一、构建的 git 版本

仓库 来源 commit
kvlang 本 PR #302 + 合并 master 613ba14 → 合并后 b2bf7cb(master = v0.2.18-6-gb2bf7cb
kvspace #16 feat/issue-268-v016 + 合并 main e185c10 → 合并后 265b340
kvspace-c #28 feat/issue-268-v016 + 合并 main 994c1af → 合并后 aaaaab3
kvspace-durable 未改(shm 基准不涉及) main 7472936

先清空系统目录里 kvspace/kvlang 的库与可执行,四个组件全部从源码重编安装(消除残留与版本混装),再跑测试与基准。

二、benchmark

python3 benchmark/run.py --backends shm(冻结 case/规模、min-of-3、Intel Xeon 8336C)

  • 本 PR:benchmark/results/results-v0.2.18-20260913T131549Z.csv
  • 同一棵树、仅把 kvlangKvConnectref_on 置 0(关缓存):results-v0.2.18-20260913T131808Z.csv
  • 基线:master results-v0.2.18-20260912T103051Z.csv

(ms)

case 规模 v0.2.18 (master) 本 PR 同树·关缓存 本PR/关缓存 关缓存/v0.2.18
binary_search N=16 6.00 6.55 5.96 1.099 0.992
binary_search N=32 12.60 13.66 12.59 1.085 0.999
binary_search N=64 27.48 26.93 0.980
binary_trees depth=4 3.90 4.48 3.81 1.176 0.978
binary_trees depth=5 7.04 8.11 6.93 1.170 0.985
binary_trees depth=6 13.89 13.81 0.995
fib n=8 8.61 8.91 8.43 1.057 0.979
fib n=9 13.82 14.50 13.66 1.061 0.988
fib n=10 22.40 23.49 22.33 1.052 0.997
hash_table N=50 3.46 3.88 3.40 1.140 0.985
hash_table N=100 6.83 7.47 6.70 1.116 0.981
hash_table N=200 14.41 14.30 0.992
iops N=500 4.14 4.68 4.07 1.150 0.985
iops N=1000 8.03 9.11 8.03 1.134 1.000
iops N=2000 16.00 18.01 15.53 1.160 0.971
k_nucleotide rep=3 6.85 7.54 1.101
k_nucleotide rep=5 13.47 16.84 15.59 1.080 1.157
k_nucleotide rep=8 26.90 34.26 32.29 1.061 1.200
matmul N=4 1.52 1.83 1.53 1.195 1.004
matmul N=6 4.13 5.02 4.01 1.253 0.970
matmul N=8 8.87 10.90 8.71 1.251 0.982
nqueens N=4 5.14 5.43 5.09 1.067 0.990
nqueens N=5 15.83 16.37 15.44 1.060 0.975
nqueens N=6 44.03 46.12 43.71 1.055 0.993
prime_sieve N=50 7.45 8.42 7.46 1.129 1.001
prime_sieve N=75 13.68 15.62 13.72 1.138 1.003
prime_sieve N=100 19.57 22.24 19.73 1.127 1.008
quicksort N=32 4.46 5.35 4.42 1.210 0.992
quicksort N=64 9.56 11.24 9.49 1.184 0.993
quicksort N=128 20.29 24.21 19.95 1.213 0.983

本PR/关缓存 中位 1.134(1.052–1.253,27 点);关缓存/v0.2.18 中位 0.992。

  1. 关缓存那一列与 v0.2.18 基线吻合(0.992),说明机器与基线正常 —— 1.13 倍的差距来自缓存路径自身
  2. 本 PR 列有 3 行 invalidbinary_search N=32binary_trees depth=6k_nucleotide rep=5,进程 SIGSEGV),关缓存列 0 行。
  3. 另一窗口(未清环境)同口径测到 1.000。两个窗口的共同点是:从未测到正收益,落在 1.00 ~ 0.87 之间。
  4. PR 描述里的 iops −13% / prime_sieve −9% / hash_table −13% 用的是 v0.2.17-14-g8e0bb9e baseline(本仓无此 commit,落后当前 master 30 个 commit),与当前 master 不可比。

三、为什么没有收益:父节点缓存当前没有生效

runtime 用的 kvspaceRef_t 是 4 字段,而 kvspace-c #28 只写前 2 个。把一个 ref 先填 0xAA 再调 ResolveRef

公开头 sizeof(kvspaceRef_t)=8   runtime 需要 16
shm://  ResolveRef rc=0 -> block_id=2 gen=0 | parent_id=0xaaaaaaaa depth=0xaaaaaaaa ← 后 8 字节未被写
fs://   ResolveRef rc=1 -> ref 原样(durable 未实现)
  • 本 PR 新增的 runtime/tests/test_getmember_siblings 在本组合下 5 项 CHECK 失败fpar.block_id==0depth==0)。
  • GetMember 热路径计数实测:GetMember=10875 hot=4001 fpar=0 pref=0 —— 只有 leaf/hot 缓存在工作,父节点缓存一次都没命中。

四、这个组合还会崩(不是性能问题)

runtime/src/kvspace.c:533kvspaceRef_t rr; 未初始化,而 kvspace-c 不写 parent_id/depth,于是读到栈垃圾(实测 parent_id=1629495328 depth=17677258822378727268/32765 这类值),被 parent_put 当作有效父节点缓存 → kvspaceGetByRef 拿野 block_idart_blk(无上界检查)→ 越界 SIGSEGV。

实验(干净重编后) 结果
shm 全量 tutorial(199 例) 189 PASS / 10 FAIL(全 SIGSEGV)
fs 全量 tutorial(199 例) 199/199(durable 没有这些符号 → 缓存不启用 → 不崩)
08-leetcode/001_two-sum-hash ×10 4/10 崩
缓存关 ×10 0/10
仅加 kvspaceRef_t rr = {0,0,0,0}; ×10 0/10
全量 tutorial(仅加零初始化) 199/199

五、CI 现在是盲的

deps.json 固定的 kvspace v0.2.18 发布版不含这三个符号(该 tag 的 src/ 里搜不到 kvspaceResolveRef)→ runtime 里三个弱符号为 NULL → ref_ok() 恒 false → 缓存整体关闭。所以 test-shm/test-fs 的 green 对这条路径没有任何信号,既测不到崩溃也测不到性能。

另外 ci-macos 的 build job 目前是红的:Undefined symbols for architecture arm64: _kvspaceGetByRef / _kvspaceResolveRef —— __attribute__((weak)) 在 Mach-O 上不等价于 ELF 的弱未定义。

六、建议

  1. 补上 kvspace-c 的另一半ResolveRefparent_id(父 ART 节点)与 depth(进入该节点时 key 已消费的字节数),GetByRef 支持从父节点续走剩余字节;并把 4 字段的 kvspaceRef_t 写进 kvspace 公开头(1-core/runtime/C 实现 core-runtime(runtime/ + rwext),KVSPACE env 统一 #16)。补齐之前,标题里的"缓存 ART 父节点"等于没有实现,只剩 miss 侧开销。
  2. kvspaceRef_t rr = {0}; 先零初始化(一行即可让上面 10 个 SIGSEGV 与 3 行 invalid 消失)。
  3. ref_ok() 改成能力探测:不要只判"符号是否存在",改为首次 ResolveRef 后若 parent_id == 0 就永久关闭父缓存。
  4. macOS 侧改 weak_import 或加 -Wl,-undefined,dynamic_lookup
  5. benchmark baseline 换到最新 master 并注明 commit;建议同时提供"同树关缓存"对照,避免把 master 自身的整体提升记成本次改动的收益。

ResolveRef 结果未初始化时 parent_id 是栈垃圾,GetByRef 越界 SIGSEGV。
嵌套 key 首次 ResolveRef 后 parent_id==0 则永久关闭父缓存(后端只写了叶子)。
Mach-O 用 weak_import + dynamic_lookup,避免旧 libkvspace 链接失败。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants