From: SASADA Koichi Date: 2012-05-18T08:20:40+09:00 Subject: [ruby-dev:45649] Re: [ruby-dev:45648] [ruby-trunk - Feature #6440] 引数にIOを渡した場合のMarshal.loadにバッファを持たせたい (2012/05/18 1:39), Glass_saga (Masaki Matsushita) wrote: > 現在のMarshalの形式では全体のサイズを知る方法がない為に、バッファを持とうとするとどうしても読み過ぎてしまいます。 > ungetcでは駄目となると、seekが可能なIOに対してのみバッファを持つようにして、最後にIO#seekで辻褄を合わせるというのはどうでしょうか。 > 高速化できるIOの種類が限られてしまいますが、互換性は崩さずに済むと思います。  面白いですね.少し考えてみました. # ご提案の「seek が効くもののみ」というのは,要するに File の時は, # って感じですかねぇ.pipe 的なもの(ソケット等)を使うのとどっちが # 用途として多いんだろう. 案1)  でかいオブジェクトをやりとりするのは意識が高い人に違いないので,もっと 意識を高く(低く?),こんな感じで workaround をしてもらう.Marshal した 文字列を Marshal して送る.メモリは食いますが,今時気にするだろうか. require 'benchmark' require 'tempfile' ary = Array.new(10_000){ "hoge" } file = Tempfile.new("foo") file2 = Tempfile.new("bar") Marshal.dump(ary, file) Marshal.dump(Marshal.dump(ary), file2) Benchmark.bm do |x| x.report do 100.times do file.rewind Marshal.load(file) end end x.report do 100.times do file2.rewind Marshal.load(Marshal.load(file2)) end end end file.close ruby 2.0.0dev (2012-05-04 trunk 35535) [i386-mswin32_100] user system total real 6.068000 0.031000 6.099000 ( 6.334804) 0.530000 0.016000 0.546000 ( 0.573573) 案2)真面目に先読み機構を入れる.  n 要素の Array を load する場合,少なくとも n byte 先読み出来ます(と いうことを調べるために,始めて Marshal フォーマット *1 を見た).m 番目 まで読み進めた段階で先読みしたバッファが不足した場合,n - m byte 先読み 出来ます.ネストしてると面倒になりますが(この情報をスタックで管理して, 一番先読み可能なものを集めて先読み,みたいな). *1: http://www.ruby-lang.org/ja/old-man/html/Marshal_A5D5A5A9A1BCA5DEA5C3A5C8.html  ちょっと,複雑に過ぎるかも. -- // SASADA Koichi at atdot dot net