You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用ScalaPB解析ByteString时如何避免数组复制?

解析com.google.protobuf.ByteString的最优实践

为什么Foo.parseFrom(bs.toByteArray())更快

你观察到的JMH结果符合protobuf的内部实现逻辑:多数情况下ByteString是ByteArrayByteString的实例(直接包装了一个字节数组),此时调用toByteArray()会直接返回内部数组的引用,完全没有数组复制开销;而bs.newInput()会创建CodedInputStream包装,引入了流读取的间接层和额外的方法调用开销,反而拖慢了速度。

是否存在更优方法

在绝大多数场景下,Foo.parseFrom(bs.toByteArray())已经是最优选择,原因如下:

  • protobuf对ByteString.toByteArray()做了针对性优化:当内部存储是原生数组时直接返回引用,无复制;仅当ByteString是基于其他来源(如分段数组、只读包装)时才会触发复制,但这种场景占比极低。
  • 尝试绕过toByteArray()的操作(比如直接强转ByteArrayByteString获取内部数组)存在风险:ByteArrayByteString是protobuf的包私有类,直接强转会导致编译或运行时的访问权限问题,且protobuf版本迭代可能会修改内部实现,破坏代码兼容性。

如果追求极致性能且能确保ByteString的内部类型,可以考虑直接使用CodedInputStream的原生实例,但实际收益微乎其微,写法如下:

CodedInputStream input = CodedInputStream.newInstance(bs);
Foo foo = Foo.parseFrom(input);
input.checkLastTagWas(0); // 确保完整解析

但这种方式的性能表现不会超过toByteArray()版本,因为本质还是基于流的读取逻辑。

总结:你的JMH测试结果已经给出了最优解——优先使用Foo.parseFrom(bs.toByteArray())。

内容的提问来源于stack exchange,提问作者Yann Moisan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 02:24:13