由已分配的 ByteString 支持的高效 okio 源?
Posted
技术标签:
【中文标题】由已分配的 ByteString 支持的高效 okio 源?【英文标题】:Efficient okio Source backed by an already allocated ByteString? 【发布时间】:2019-06-29 03:43:31 【问题描述】:使用 OkHttp Websocket 时,listener 使用 ByteString 向应用程序提供二进制有效负载。 我想将这些字节输入到一些采用 okio.Source(在本例中为 GzipSource)的代码中,但我找不到任何有效地执行此操作的好方法。
我目前的解决方案是这样的:
@Override
public void onMessage(WebSocket webSocket, ByteString bytes)
Buffer gzipBuffer = new Buffer();
gzipBuffer.write(bytes);
GzipSource gzipSource = new GzipSource(gzipBuffer);
....
这个Buffer.write
的缺点是它会产生额外的字节副本(在 Buffer 的情况下,是分段的,即使池化也是额外的开销)。在这个 Websocket 案例中,一个字节数组只是为 ByteString 本身分配的(当从 WebSocketReader
impl 移交时)。
我的问题是:是否有任何其他首选方式可以通过Source
读取ByteString
?
由于ByteString
应该是不可变的,而Source
只会保存一些读取位置信息,我认为它应该是完全可行的(但不是来自外部代码,因为我无法访问byte[]
)..所以感觉我在这里错过了一个明显的解决方案.. :)
感谢任何提示或指点!
【问题讨论】:
【参考方案1】:您编写它的方式几乎是最佳的。
Okio 已针对在转换层之间移动数据进行了优化:压缩、成帧、线程等。虽然在层之间移动数据非常快(无副本),但最初将数据导入系统是有前期成本的。这通常是您无论如何都需要做的 I/O:加载文件或发送数据包。但在这种情况下,您必须复制才能将字节放入第一个缓冲区。这感觉效率低下,但好处是你的下一个 Source.read() 调用会很快,所以整体效果仍然很好。
【讨论】:
感谢您的回复。您正在写“接近最佳”,还有改进的余地吗?进一步挖掘,我看到 GzipSource 依赖于具有内部缓冲区段的源(实际上是 BufferedSource)。我认为这就是需要这种前期负载的原因,因为它无法使用该实现在单个长byte[]
上工作?因此,要支持这样的来源,它需要被重写,然后当然不能与其他来源兼容。
是的,就是这样。单个byte[]
不起作用。以上是关于由已分配的 ByteString 支持的高效 okio 源?的主要内容,如果未能解决你的问题,请参考以下文章
Haskell语言学习笔记(49)ByteString Text
PubSub 模拟器 - ( 支持 Proto Buffer 发布/接收消息)