运维开发网

如何在Ruby中有效地切片二进制数据?

运维开发网 https://www.qedev.com 2020-04-03 17:30 出处:网络 作者:运维开发网整理
在检查了SO Ruby: Split binary data后,我使用了以下代码. z = 'A' * 1_000_000 z.bytes.each_slice( STREAMING_CHUNK_SIZE ).each do | chunk | c = chunk.pack( 'C*' ) end 但是,它很慢: Benchmark.realtime do ... => 0.098394
在检查了SO Ruby: Split binary data后,我使用了以下代码.

z = 'A' * 1_000_000
z.bytes.each_slice( STREAMING_CHUNK_SIZE ).each do | chunk | 
  c = chunk.pack( 'C*' )
end

但是,它很慢:

Benchmark.realtime do
  ...
=> 0.0983949700021185

98ms切片并打包1MB文件.这很慢.

使用案例:

服务器从外部API接收二进制数据,并使用socket.write chunk.pack(‘C *’)对其进行流式处理.

数据预计在50KB到5MB之间,平均为500KB.

那么,如何在Ruby中有效地分割二进制数据呢?

笔记

您的代码看起来不错,使用正确的Ruby方法和正确的语法,但它仍然:

>创建一个巨大的整数数组

>在多个阵列中切割这个大数组

>将这些数组打包回String

替代

以下代码直接从字符串中提取部分,而不转换任何内容:

def get_binary_chunks(string, size)
  Array.new(((string.length + size - 1) / size)) { |i| string.byteslice(i * size, size) }
end

(string.length size – 1)/ size)只是为了避免丢失最后一个chunk,如果它小于size.

性能

使用500kB的pdf文件和12345字节的块,Fruity返回:

Running each test 16 times. Test will take about 28 seconds.
_eric_duminil is faster than _b_seven by 380x ± 100.0

在这个例子中,get_binary_chunks也比StringIO#each(n)快6倍.

进一步优化

如果你确定该字符串是二进制的(不是带有多字节字符的UTF8,如’ä’),则可以使用slice而不是byteslice

def get_binary_chunks(string, size)
  Array.new(((string.length + size - 1) / size)) { |i| string.slice(i * size, size) }
end

这使得代码更快(与您的方法相比大约500倍).

如果将此代码与Unicode字符串一起使用,则块将具有大小字符,但可能具有大于字节的大小.

直接使用块

最后,如果您对获取字符串数组不感兴趣,可以直接使用这些块:

def send_binary_chunks(socket, string, size)
  ((string.length + size - 1) / size).times do |i|
    socket.write string.slice(i * size, size)
  end
end

扫码领视频副本.gif

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号