背景
在 PERF-2a (per-thread bump arena) 之后,perf profile 显示剩余热点分布非常平坦(排除模拟负载后无单一热点超过 8%)。以下四个微优化已验证正确性(cross-validate 全通过),但在 realistic_for_you_calibrated fixture 上无可测量 QPS 提升(维持 ~183 QPS)。
留待将来有 data_parallel fixture 或更大 map 场景时验证收益。
优化内容
1. 窗口视图跳过锁(RowFrame + ColumnFrame)
动机: pthread_rwlock 占 5.5%。Window view 在 parallel_execute 期间保证父 frame 冻结,shared_lock 是纯开销。
原理: is_window_view() 为 true 时,所有读方法直接访问 view_items_/view_common_ 指针,不获取 shared_lock。安全性由 parallel_execute 的生命周期保证。
当前 fixture 无效原因: realistic_for_you_calibrated 的 38 个算子全部 data_parallel=0,不创建窗口视图。
2. JSON 序列化消除二次 hash 查找
动机: write_json_value 和 result_items_to_json 中,先收集 key 指针排序,再对每个 key 调用 map.find(key) — 这是冗余的 O(1) hash 查找。
原理: 改为收集 pair<const string*, const JsonValue*> 排序,直接通过指针访问 value,消除排序后的二次查找。
当前 fixture 无效原因: JSON 序列化中 find 只占总 find 热点的一小部分(大部分 find 来自算子读 frame)。
3. 数字格式化避免临时 string
动机: go_format_json_number 每次返回 std::string,在 write_json_value 中每个数字都分配临时 string。
原理: 新增 go_format_json_number_buf(double, char*, size_t) 直接写入栈 buffer,避免 heap 分配。
当前 fixture 无效原因: 数字通常 < 15 字符,在 SSO 范围内,原本就不触发堆分配。
4. to_result 预分配
动机: _M_need_rehash + _M_next_bkt 占 2.2%。to_result 中每行创建空 map 逐字段插入会触发 rehash。
原理: 对输出 map 调用 reserve(item_out.size())。
当前 fixture 无效原因: 输出字段数少(~5),默认 bucket count 已足够。
Patch
点击展开 patch
$(cat /tmp/perf-micro-opts.patch)
验证结果
- 单元测试: 145 tests passed
- Cross-validate section 4: 91/91
- Cross-validate section 5: 26/26
- Benchmark: ~183 QPS(与基线持平)
适用场景
这些优化在以下场景可能有可测量收益:
- 使用
data_parallel 的 fixture(窗口视图跳过锁)
- 输出字段数 > 10 的 pipeline(reserve 预分配)
- 大量嵌套 object 的 JSON 序列化(消除二次 find)
背景
在 PERF-2a (per-thread bump arena) 之后,perf profile 显示剩余热点分布非常平坦(排除模拟负载后无单一热点超过 8%)。以下四个微优化已验证正确性(cross-validate 全通过),但在
realistic_for_you_calibratedfixture 上无可测量 QPS 提升(维持 ~183 QPS)。留待将来有 data_parallel fixture 或更大 map 场景时验证收益。
优化内容
1. 窗口视图跳过锁(RowFrame + ColumnFrame)
动机:
pthread_rwlock占 5.5%。Window view 在parallel_execute期间保证父 frame 冻结,shared_lock 是纯开销。原理:
is_window_view()为 true 时,所有读方法直接访问view_items_/view_common_指针,不获取 shared_lock。安全性由 parallel_execute 的生命周期保证。当前 fixture 无效原因:
realistic_for_you_calibrated的 38 个算子全部data_parallel=0,不创建窗口视图。2. JSON 序列化消除二次 hash 查找
动机:
write_json_value和result_items_to_json中,先收集 key 指针排序,再对每个 key 调用map.find(key)— 这是冗余的 O(1) hash 查找。原理: 改为收集
pair<const string*, const JsonValue*>排序,直接通过指针访问 value,消除排序后的二次查找。当前 fixture 无效原因: JSON 序列化中 find 只占总 find 热点的一小部分(大部分 find 来自算子读 frame)。
3. 数字格式化避免临时 string
动机:
go_format_json_number每次返回std::string,在write_json_value中每个数字都分配临时 string。原理: 新增
go_format_json_number_buf(double, char*, size_t)直接写入栈 buffer,避免 heap 分配。当前 fixture 无效原因: 数字通常 < 15 字符,在 SSO 范围内,原本就不触发堆分配。
4. to_result 预分配
动机:
_M_need_rehash+_M_next_bkt占 2.2%。to_result中每行创建空 map 逐字段插入会触发 rehash。原理: 对输出 map 调用
reserve(item_out.size())。当前 fixture 无效原因: 输出字段数少(~5),默认 bucket count 已足够。
Patch
点击展开 patch
验证结果
适用场景
这些优化在以下场景可能有可测量收益:
data_parallel的 fixture(窗口视图跳过锁)