Skip to content

v1.9.0 · 性能:打开表格快 1483 倍 · 清理 757 MB

Choose a tag to compare

@YJLZSL YJLZSL released this 26 Sep 03:55
· 11 commits to main since this release

性能(实测,不是估的)

先加了性能基线测试(perf_baseline_page_and_search,#[ignore] 手动跑),
因为它要插 10 万行、进 CI 会让每次提交都变慢;但必须能手动跑 ——
性能数字不能靠感觉,也不能靠回忆。

优化前(本机实测):

规模 插入 首页 游标页 筛选
1 万行 168ms 28.4ms 26.3ms 27.5ms
10 万行 1.81s 336ms 329ms 331ms

病根(查出来的,不是猜的):store::scan 会把整表克隆出来 ——
每行一个 key 的 String 加一个 value 的 String,然后逐行 JSON 反序列化。
而最常见的查询是"打开表格看第一页":为了显示 50 行,去克隆 10 万个 String。
三个指标数字几乎一样,正是"卡在同一个地方"的证据。

改法:加 store::scan_take(prefix, n)(只取前 n 条),
在 page_rows_filtered 里加一条快路径 —— 无筛选、无游标、按 rowid 升序时直接取前若干行。

这条快路径能成立,靠的是一个已存在的事实:记录 key 是
rec/<表>/<20 位补零 rowid>,所以 BTreeMap 的字典序就是 rowid 升序。
补零是关键 —— 换成不补零的数字串,10 会排在 9 前面,这条快路径就不成立了。

优化后:

规模 首页 变化
1 万行 28.4ms → 0.31ms 快 93 倍
10 万行 336ms → 0.23ms 快 1483 倍

还没优化的(如实说):游标页与筛选仍是 ~330ms。
它们必须看全部行(游标要定位、筛选要逐行比),不是"也能顺手改掉"的东西 ——
要做需要倒排索引或增量扫描,是另一个量级的工程。

过程中被测试抓到一个我引入的 bug:快路径起初只取 limit 行,
而 finish_page 靠"多出来的那一行"判断 has_more,于是"还有 50 行没取"却报 has_more=false。
分页测试当场失败。改成取 limit + 1 行。
(这件事的意义:改动查询逻辑时,旧测试是最好的保险 —— 它比我先发现问题。)

清理

仓库瘦身 757 MB(23 项):

内容 处理
poc/*/node_modules target-msvc(约 700 MB) 删缓存,源码保留(AGENTS 明确:缓存可删、源码不要删)
dist/ 旧版本 zip(31 个) 删,保留最近 3 个;GitHub Release 里都有
local-docs/runs/ 旧走查目录 删,保留最近 5 个

体检结论(顺带做的)

项 结果
编译警告 0 条
#[allow(dead_code)] 5 处(都是有理由的)
前端函数跨文件重名 17 组,但全部是 IIFE 独立作用域,不构成问题
最大文件 main.rs 4480 行(主要是 dispatch 的巨型 match)

关于 main.rs 要不要拆:暂时不拆。那个 match 是 check-wiring 门禁的
识别形式,拆它有真实风险而收益只是"文件数字好看一点"。不做没有把握的重构。

验证

单元 265 通过 / 0 失败 · 烟测 112/112 · 门禁五道 ·
性能数字为本机实测(cargo test perf_baseline -- --ignored --nocapture)


[1.9.0] - 2026-09-26 · 性能:打开表格快 1483 倍 · 仓库清理 757 MB

性能(实测,不是估的)

先加了性能基线测试(perf_baseline_page_and_search,#[ignore] 手动跑),
因为它要插 10 万行、进 CI 会让每次提交都变慢;但必须能手动跑 ——
性能数字不能靠感觉,也不能靠回忆。

优化前(本机实测):

规模 插入 首页 游标页 筛选
1 万行 168ms 28.4ms 26.3ms 27.5ms
10 万行 1.81s 336ms 329ms 331ms

病根(查出来的,不是猜的):store::scan 会把整表克隆出来 ——
每行一个 key 的 String 加一个 value 的 String,然后逐行 JSON 反序列化。
而最常见的查询是"打开表格看第一页":为了显示 50 行,去克隆 10 万个 String。
三个指标数字几乎一样,正是"卡在同一个地方"的证据。

改法:加 store::scan_take(prefix, n)(只取前 n 条),
在 page_rows_filtered 里加一条快路径 —— 无筛选、无游标、按 rowid 升序时直接取前若干行。

这条快路径能成立,靠的是一个已存在的事实:记录 key 是
rec/<表>/<20 位补零 rowid>,所以 BTreeMap 的字典序就是 rowid 升序。
补零是关键 —— 换成不补零的数字串,10 会排在 9 前面,这条快路径就不成立了。

优化后:

规模 首页 变化
1 万行 28.4ms → 0.31ms 快 93 倍
10 万行 336ms → 0.23ms 快 1483 倍

还没优化的(如实说):游标页与筛选仍是 ~330ms。
它们必须看全部行(游标要定位、筛选要逐行比),不是"也能顺手改掉"的东西 ——
要做需要倒排索引或增量扫描,是另一个量级的工程。

过程中被测试抓到一个我引入的 bug:快路径起初只取 limit 行,
而 finish_page 靠"多出来的那一行"判断 has_more,于是"还有 50 行没取"却报 has_more=false。
分页测试当场失败。改成取 limit + 1 行。
(这件事的意义:改动查询逻辑时,旧测试是最好的保险 —— 它比我先发现问题。)

清理

仓库瘦身 757 MB(23 项):

内容 处理
poc/*/node_modules target-msvc(约 700 MB) 删缓存,源码保留(AGENTS 明确:缓存可删、源码不要删)
dist/ 旧版本 zip(31 个) 删,保留最近 3 个;GitHub Release 里都有
local-docs/runs/ 旧走查目录 删,保留最近 5 个

体检结论(顺带做的)

项 结果
编译警告 0 条
#[allow(dead_code)] 5 处(都是有理由的)
前端函数跨文件重名 17 组,但全部是 IIFE 独立作用域,不构成问题
最大文件 main.rs 4480 行(主要是 dispatch 的巨型 match)

关于 main.rs 要不要拆:暂时不拆。那个 match 是 check-wiring 门禁的
识别形式,拆它有真实风险而收益只是"文件数字好看一点"。不做没有把握的重构。

验证

单元 265 通过 / 0 失败 · 烟测 112/112 · 门禁五道 ·
性能数字为本机实测(cargo test perf_baseline -- --ignored --nocapture)