feat: 优化 token_estimator.go 热路径性能,消除每次调用的字符串重建和线性扫描 #3428
feat: 优化 token_estimator.go 热路径性能,消除每次调用的字符串重建和线性扫描 #3428GYMmaorui wants to merge 1 commit intoQuantumNous:mainfrom
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
WalkthroughThis pull request optimizes the token estimator module by removing synchronization overhead and replacing linear character-list scans with precomputed lookup sets for O(1) membership checks. It also adds comprehensive unit tests and performance benchmarks to validate the optimized behavior across various input types and model providers. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
new api在流量很小的情况下也会出现cpu打满的情况,触发503拒绝。我们使用pprof导出了cpu满载时期的火焰图,由claude分析并修改定位。 |
Summary
isMathSymbol()中每次调用都重建的 90+ 字符字符串 + O(n) 线性扫描,替换为包级别预计算的map[rune]struct{}O(1) 查找,miss 路径提升 ~47 倍isURLDelim()同样改为预计算 map 查找multipliersMap上无意义的sync.RWMutex(该 map 初始化后从未被写入,锁纯属浪费)getMultipliers()为直接 map 查找 + fallback,移除冗余 switchtoken_estimator_test.go:7 个功能正确性测试 + 15 个基准测试(含新旧实现对比)Background
isMathSymbol()在 token 估算的主循环中被高频调用:对每个非字母/非数字/非 CJK/非 emoji/非空格的字符都会执行一次。旧实现每次调用都构造一个包含 90+ 个 Unicode 字符的字符串,然后range遍历逐个比较。在高并发场景下,token 估算有两条触发路径:
CountToken=false环境变量关闭ResponseText2Usage):无独立开关,当上游未返回 usage 时自动触发响应侧无法通过配置关闭,只能通过代码优化解决。一个 10KB 的响应文本中如果有 1000 个符号字符,旧实现需要约 90,000 次比较 + 1000 次字符串构造。
Changes
service/token_estimator.go将
isMathSymbol()的字符串替换为包级别预计算的 map:isURLDelim()同理。移除无意义的读写锁(
multipliersMap初始化后只读,全局搜索确认无写入):service/token_estimator_test.go(新增)isMathSymbol、isURLDelim、getMultipliers、EstimateToken、EstimateTokenByModel的正确性和确定性Benchmark
测试环境:Apple M4, Go 1.22
核心函数新旧对比
isMathSymbolisMathSymbolisURLDelimmiss 是最关键的路径:绝大多数字符(英文、空格、CJK 等)都不是数学符号,每个都走 miss 分支。
端到端
EstimateToken(优化后,0 allocs/op)Test plan
go build ./...编译通过Summary by CodeRabbit
Performance Improvements
Tests