新手问题 ruby 读写大量 bin 文件的内存波动

u4crella · 2019年12月14日 · 最后由 u4crella 回复于 2019年12月14日 · 2262 次阅读

自己写了个解析 m3u8 并下载 ts 视频文件的脚本,已知该网站没有反爬。 现在暂时是 ruby 解析 m3u8 生成 aria2 可读的 txt 列表,然后用 aria2 -i 下载列表.txt 作为后端来下载,最后用 ffmpeg 合成文件。

刚才想了一下能不能用 ruby 自带的 http 库来下载,然后直接以 binmode 打开、连接、生成最终的 mkv 文件。但是一想起之前某些不成熟的 ruby 脚本爆内存,心里就有些忐忑不安。

刚才测试了一下,对 ruby 占用的内存的浮动表示非常疑惑。500 个 ts 文件,在硬盘上也就占用 244MB 空间,但是 ruby 的内存占了 744MB,内存波动最高占用了 1057MB。(注:全部 ts 文件在硬盘上占用空间是 887MB)

因此想问问代码、流程或者思路有没有可以改善的地方。

环境是 ruby2.5.7 x64 mingw32 Windows7

require 'c:/rlib/tsutils.rb'
puts 'waiting..'; gets
filenames = parselist("./index.m3u8") #返回[hash1, hash2, ...hashN]
main_file_content = ''
(0..500).each {|fid|
  tmp_filename = filenames[fid][:fname] # m3u8中某行链接的文件名
  fio = File.open( tmp_filename, 'rb')
  tmpfile = fio.read
  main_file_content  = main_file_content  + tmpfile
  fio.close  
  tmpfile = nil; 
}
puts 'waiting..'; gets

想起了c#的stringbuilder,于是到stackoverflow上搜索了ruby连接字符串的方式。发现把代码的第9行,用'+'号连接字符串改为:

main_file_content  << tmpfile

这样就快了快十倍,最后消耗了 310MB 内存,比较理想,从 ruby-prof 的记录看到也没什么问题了。 用'+'号连接字符串的时候,ruby-prof 提示 String#+ 消耗了大量 cpu。

不推荐用 ruby 的 binmode 读写来合并 ts 文件,这种方式生成的 mkv 比 ffmpeg -f concat 生成的 mkv 大几十 MB。时间长度也不一致,不过内容好像没有差异。还是更愿意相信 ffmpeg。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号