gpt4 book ai didi

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

转载 作者:数据小太阳 更新时间:2023-10-29 07:24:27 32 4
gpt4 key购买 nike

在查看 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

切片和打包 1MB 文件需要 98 毫秒。这非常慢。

用例:
服务器从外部 API 接收二进制数据,并使用 socket.write chunk.pack( 'C*' ) 对其进行流式处理。
数据预计在50KB到5MB之间,平均500KB。

那么,如何在 Ruby 中高效地对二进制数据进行切片?

最佳答案

注意事项

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

  • 创建一个巨大的整数数组
  • 将这个大数组分割成多个数组
  • 将这些数组打包回字符串

备选

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

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) 只是为了避免在小于 size 的情况下丢失最后一个 block 。

性能

对于 500kB 的 pdf 文件和 12345 字节的 block ,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 字符串一起使用, block 将具有 size 个字符,但可能超过 size 个字节。

直接使用 block

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

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

关于ruby - 如何在 Ruby 中有效地切片二进制数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41432582/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com