ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

BAML 字符串 split 长字面量基准:从 speedtest Workload 定义到零拷贝底层实现

BAML 字符串 split 长字面量基准:从 speedtest Workload 定义到零拷贝底层实现 编程语言AI Agent编译器CLI人工智能【免费下载链接】bamlThe programming language for agents项目地址https://gitcode.com/gh_mirrors/ba/baml点击查看免费下载本指南以仓库中 split-long-literal-1k.md 为解剖对象讲解 BAML 性能基准工具speedtest如何用一份 Markdown 同时定义 BAML / Python / TypeScript 三语言等价基准验证string.split在长字符串、多分隔符场景下的行为与性能并结合 bex_vm 的源码剖析 split 的零拷贝实现原理。读完本文你将理解该 Workload 的模板变量机制、三端代码的等价关系、可预期的输出结果以及如何用speedtestCLI 单独筛选、运行并对比这一基准。一、这个 Workload 在测什么基准设计的核心意图string::split long literal 1k属于speedtest基准套件中string分类下的一个用例其命名可以拆解为三部分string::split被测对象是字符串内建方法split(delim)long literal输入是一段接近 200 字符的自然语言长字面量而不是hello world这类短串1k基准循环 1000 次强调长输入 × 高频调用的组合。与同目录下的姊妹基准对比能更清楚它的定位Workload输入规模迭代次数侧重string-split-100k.md短字面量hello world foo bar baz qux100000短串高频 split 开销split-short-literal-100k.md短字面量100000短字面量场景split-medium-literal-10k.md约 200 字符、8 段、\|分隔10000中等字面量split-long-literal-1k.md本文约 200 字符 × 10 段、###分隔1000长字面量、多段分隔该 Workload 的核心假设是BAML 的split在长字符串上不应产生明显的分配开销——因为底层实现是零拷贝的。下一节先还原它的完整定义再在第四节用源码验证这个假设。二、文档结构剖析一份 Markdown 如何驱动三语言基准该 Workload 文件遵循speedtest套件的统一格式一个#标题、一个可选的## eval-setup段、以及## BAML/## Python/## Typescript三个代码段。解析逻辑位于 loader.py正则^#\s(.)提取标题作为 workload 名称string::split long literal 1k正则 ^##\s([\w-])\s*\n\w*\n(.*?) 切出各代码段若存在eval-setup通过exec在受限命名空间中执行产出模板变量各语言代码段经模板替换后得到可执行源码。eval-setup用 Python 生成三端共享的输入eval-setup是一段在基准加载时执行的 Python 代码负责构造输入数据并导出三种语言各自的字面量转义形式import json chunk ( the quick brown fox jumps over the lazy dog and runs through the meadow while the sun sets behind the distant mountains casting long shadows across the rolling hills and the gentle breeze carries the scent of wildflowers and freshly cut grass through the warm summer air as birds sing in the trees and the world feels at peace with itself in this perfect moment of stillness and beauty that seems to stretch on forever without end or care for the troubles of yesterday or tomorrow only the present moment matters now ) src ###.join([chunk] * 10) delim ### baml_src json.dumps(src) baml_delim json.dumps(delim) py_src repr(src) py_delim repr(delim) js_src json.dumps(src) js_delim json.dumps(delim)这里的关键设计是一份数据、三份转义src把一段约 200 字符的自然语言chunk用###连接 10 次得到约 2000 字符、含 9 个分隔符的长串baml_src/baml_delimJSON 转义双引号字符串供 BAML 代码段使用py_src/py_delimPythonrepr转义保证换行、引号等字符被安全编码js_src/js_delimJSON 转义供 TypeScript/Node 使用。模板变量机制$$前缀的巧思模板替换由 loader 内部的_DDTemplate完成它继承自 Python 标准库string.Template并将定界符改为$$class _DDTemplate(Template): Template using $$var instead of $var, so single $ is literal. delimiter $$选择$$var而不是$var是有意为之eval-setup 生成的字符串本身包含大量$例如 JSON 转义内容若沿用默认$定界符会产生误替换改用$$后只有$$baml_src、$$baml_delim这类显式占位符会被替换其余$全部按字面保留。替换采用safe_substitute未定义的$$xxx会原样保留而非抛错。三、三语言代码对照语义等价的可执行基准模板替换完成后三份代码在语义上完全等价这是跨语言对比成立的前提。BAMLfunction main() - int { let s $$baml_src; let delim $$baml_delim; let count 0; for (let i 0; i 1000; i 1) { let parts s.split(delim); count parts.length(); }; return count; }要点s.split(delim)返回一个数组parts.length()取段数累加 1000 次后作为int返回。src由 10 段连接而成含 9 个###分隔符因此每次 split 得到10 个部分最终返回值是1000 × 10 10000。Pythons $$py_src delim $$py_delim c 0 for _ in range(1000): c len(s.split(delim)) print(c)Python 的str.split(delim)同样把10 段 / 9 分隔符切成 10 个元素print(c)输出 10000。TypeScriptconst s $$js_src; const delim $$js_delim; let c 0; for(let i0;i1000;i) c s.split(delim).length; console.log(c);String.prototype.split对非空定界符同样返回 10 个元素console.log(c)输出 10000。三端在语义上等价非空定界符、无尾随空段因此基准框架可以在计时之前先做跨语言输出校验——见第五节。四、底层实现验证split 的零拷贝语义基准之所以把长字面量 高频调用作为考察点与底层实现方式直接相关。BAML 运行时中字符串方法由 package_baml/string.rs 提供split的实现如下// Zero-copy: each segment is a zero-copy substring Slice into the original. fn split(string: BexStr, delimiter: BexStr) - VecBexStr { let s string.as_str(); let d delimiter.as_str(); if d.is_empty() { return char_substrings(string); } let base s.as_ptr() as usize; s.split(d) .map(|part| { let start part.as_ptr() as usize - base; string.substring(start, start part.len()) }) .collect() }实现要点零拷贝切片用 Rust 标准库str::split(d)遍历分隔位置对每个子串计算它在原字符串中的字节偏移start再调用string.substring(start, start len)生成切片。每个段都是指向原字符串内存的BexStr切片不复制字符数据——这正是注释Zero-copy的含义空定界符特判d.is_empty()时退化为char_substrings即按 Unicode 码点逐字符切分这与 JavaScriptabc.split()返回单个字符数组的行为一致共享 substr 基建lines按行切分等相邻方法也复用相同的指针偏移 substring模式说明该零拷贝思路在字符串族方法中是统一约定。由此可以推断本 Workload 中 1000 次对约 2000 字符长串的 split 主要开销来自分割遍历与结果数组构建而非字符数据拷贝这也是它与短串高频场景如string-split-100k在测量维度上的本质区别。五、如何运行与复用这个 Workloadspeedtest是仓库baml_language/tools/speedtest下的 Python 工具包入口配置见 pyproject.toml脚本入口为speedtest speedtest.cli:main提供run/compare/open/list/baselines五个子命令参数定义见 cli.py。单独跑长字面量 split 基准# 构建 release 版 baml-cli 后仅运行名称匹配 split-long-literal 的 workload speedtest run --build --filter split-long-literal常用参数参数作用--filter STR只跑名称包含该子串的 workload可重复指定多个--only-baml跳过 Python / Node / Bun只测 BAML--runs N固定跑 N 次默认走自适应计时--measurement-time SECS自适应模式下每个 workload 的目标总时长默认 5 秒--tag NAME为本次运行打标签便于后续对比--profile用samply record采集 CPU profile--results-dir DIR结果保存目录默认~/.speedtest/run的执行流程见 runner.py分五步打包调用baml-cli pack main --file w.baml -o w.packed把该 Workload 的 BAML 源码编译为独立可执行文件取基准输出运行打包产物取最后一行 stdout 作为期望结果本 Workload 应为10000跨语言校验依次运行python3 -S、node、bun可用时若输出与期望不一致则标记mismatch——这正是三端语义等价性被自动验证的环节计时先做 3 次预热丢弃、暖 OS 缓存再按目标时长自适应采样样本数限制在[5, 100]统计中位数、标准差、最小/最大值落盘结果保存到results/与baselines/branch/latest支持后续对比。对比与查看speedtest compare base new # 对比两个基线 speedtest compare base new --threshold 5 # 忽略变化幅度小于 5% 的项 speedtest list # 列出全部 workload 名称 speedtest open # 浏览器打开结果 UI复用为 Rust CodSpeed 基准仓库还提供了 export_baml.py 作为桥接脚本它复用loader.load_workloads把每个 Workload 的展开后BAML 源码导出为 JSON 数组{name, category, baml}供crates/baml_tests作为 CodSpeed 基准直接复用避免在 Rust 侧重复实现.md解析、eval-setup 执行与$$模板替换逻辑。六、围绕该 Workload 的扩展阅读路径若想深入该基准所依赖的运行时能力可按以下路径继续探索split 运行时实现bex_vm/src/package_baml/string.rs 中split及lines、chars、slice等字符串族方法的零拷贝实现Workload 解析与模板speedtest/loader.py 中parse_workload_md、_DDTemplate与load_workloads计时与打包speedtest/runner.py 中自适应计时time_command_adaptive与打包pack_baml同类基准对照string分类下其余 7 个 Workloadworkloads/string/可用于横向对比不同输入规模下 split、contains、concat、substring、trim 的性能特征。七、小结本 Workload 验证了什么string::split long literal 1k用一份 Markdown 同时刻画了三件事测试方法通过eval-setup$$模板变量在加载期为 BAML / Python / TypeScript 生成字节级一致的长输入保证三端基准的公平性语义契约三端代码对同一输入必须产出同一结果10000并由 runner 在计时前自动校验防止测了不同的事实现特征长字面量高频 split 是零拷贝切片路径的代表性负载其性能特征与短串场景存在本质差异。对于想要为 BAML 新增或修改字符串内建方法的开发者这份 Workload 既是一份可复用的性能回归用例也是一份可运行的语义验证样例。赞分享编程语言AI Agent编译器CLI人工智能【免费下载链接】bamlThe programming language for agents项目地址https://gitcode.com/gh_mirrors/ba/baml点击查看免费下载相关推荐Roc 字符串前缀移除实战从 Str.drop_prefix 快照测试看 REPL、底层实现与零拷贝切片Roc 字符串前缀移除实战从 Str.drop_prefix 快照测试看 REPL、底层实现与零拷贝切片 Str.drop_prefix 是 Roc 标准库中Rakam-API高级功能Webhook集成与实时事件处理Rakam API高级功能Webhook集成与实时事件处理 在当今数据驱动的世界中 实时事件处理 和 Webhook集成 已成为现代应用分析的核心需求编程语言AI Agent编译器CLI人工智能从B树到字符串比较db_tutorial中SQL字符串操作的底层实现从B树到字符串比较db_tutorial中SQL字符串操作的底层实现 在数据库应用中字符串比较是最常用的操作之一无论是用户登录时验证用户名还是按邮箱地址示例工程上一篇Twire高级技巧画质设置与横屏聊天窗口的隐藏功能下一篇在Docker中畅玩Windows1GB内存也能轻松驾驭创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表