https://bugs.ruby-lang.org/
https://bugs.ruby-lang.org/favicon.ico?1711330511
2012-05-17T00:57:32Z
Ruby Issue Tracking System
Ruby master - Feature #6440: 引数にIOを渡した場合のMarshal.loadにバッファを持たせたい
https://bugs.ruby-lang.org/issues/6440?journal_id=26666
2012-05-17T00:57:32Z
mame (Yusuke Endoh)
mame@ruby-lang.org
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Assigned</i></li><li><strong>Assignee</strong> set to <i>nobu (Nobuyoshi Nakada)</i></li></ul><p>なんとなくなかださんに。</p>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a></p>
Ruby master - Feature #6440: 引数にIOを渡した場合のMarshal.loadにバッファを持たせたい
https://bugs.ruby-lang.org/issues/6440?journal_id=26676
2012-05-17T13:22:54Z
nobu (Nobuyoshi Nakada)
nobu@ruby-lang.org
<ul></ul><p>=begin<br>
細かい問題を修正すればいいんじゃないですかね。</p>
<ul>
<li>(({struct load_arg.buf}))のメモリリーク</li>
<li>(({r_bytes1_partial()}))で(({readpartial}))での不足分を(({read}))で追加したときに((|tmp_ptr|))が不正</li>
</ul>
<p>あとは感想をいくつか。</p>
<ul>
<li>(({arg->partial}))をフラグにするよりsymbolを持たせてはどうか</li>
<li>(({r_bytes()}))と(({r_bytes0()}))の追加部分は関数に分けることはできないだろうか</li>
<li>予約語((({if})))とカッコの間が空いていない<br>
=end</li>
</ul>
Ruby master - Feature #6440: 引数にIOを渡した場合のMarshal.loadにバッファを持たせたい
https://bugs.ruby-lang.org/issues/6440?journal_id=26677
2012-05-17T13:27:57Z
nobu (Nobuyoshi Nakada)
nobu@ruby-lang.org
<ul><li><strong>Description</strong> updated (<a title="View differences" href="/journals/26677/diff?detail_id=19712">diff</a>)</li></ul><p>=begin<br>
もう一点、(({s_getbyte}))も不要になるはずです。<br>
=end</p>
Ruby master - Feature #6440: 引数にIOを渡した場合のMarshal.loadにバッファを持たせたい
https://bugs.ruby-lang.org/issues/6440?journal_id=26684
2012-05-18T01:39:05Z
Glass_saga (Masaki Matsushita)
glass.saga@gmail.com
<ul></ul><p>なかださん、田中さん、レビューとご意見をありがとうございます。</p>
<p>現在のMarshalの形式では全体のサイズを知る方法がない為に、バッファを持とうとするとどうしても読み過ぎてしまいます。<br>
ungetcでは駄目となると、seekが可能なIOに対してのみバッファを持つようにして、最後にIO#seekで辻褄を合わせるというのはどうでしょうか。<br>
高速化できるIOの種類が限られてしまいますが、互換性は崩さずに済むと思います。</p>
Ruby master - Feature #6440: 引数にIOを渡した場合のMarshal.loadにバッファを持たせたい
https://bugs.ruby-lang.org/issues/6440?journal_id=26689
2012-05-18T08:23:13Z
ko1 (Koichi Sasada)
<ul></ul><p>(2012/05/18 1:39), Glass_saga (Masaki Matsushita) wrote:</p>
<blockquote>
<p>現在のMarshalの形式では全体のサイズを知る方法がない為に、バッファを持とうとするとどうしても読み過ぎてしまいます。<br>
ungetcでは駄目となると、seekが可能なIOに対してのみバッファを持つようにして、最後にIO#seekで辻褄を合わせるというのはどうでしょうか。<br>
高速化できるIOの種類が限られてしまいますが、互換性は崩さずに済むと思います。</p>
</blockquote>
<p> 面白いですね.少し考えてみました.</p>
<a name="ご提案のseek-が効くもののみというのは要するに-File-の時は"></a>
<h1 >ご提案の「seek が効くもののみ」というのは,要するに File の時は,<a href="#ご提案のseek-が効くもののみというのは要するに-File-の時は" class="wiki-anchor">¶</a></h1>
<a name="って感じですかねぇpipe-的なものソケット等を使うのとどっちが"></a>
<h1 >って感じですかねぇ.pipe 的なもの(ソケット等)を使うのとどっちが<a href="#って感じですかねぇpipe-的なものソケット等を使うのとどっちが" class="wiki-anchor">¶</a></h1>
<a name="用途として多いんだろう"></a>
<h1 >用途として多いんだろう.<a href="#用途として多いんだろう" class="wiki-anchor">¶</a></h1>
<p>案1)<br>
でかいオブジェクトをやりとりするのは意識が高い人に違いないので,もっと<br>
意識を高く(低く?),こんな感じで workaround をしてもらう.Marshal した<br>
文字列を Marshal して送る.メモリは食いますが,今時気にするだろうか.</p>
<p>require 'benchmark'<br>
require 'tempfile'</p>
<p>ary = Array.new(10_000){ "hoge" }<br>
file = Tempfile.new("foo")<br>
file2 = Tempfile.new("bar")<br>
Marshal.dump(ary, file)<br>
Marshal.dump(Marshal.dump(ary), file2)</p>
<p>Benchmark.bm do |x|<br>
x.report do<br>
100.times do<br>
file.rewind<br>
Marshal.load(file)<br>
end<br>
end<br>
x.report do<br>
100.times do<br>
file2.rewind<br>
Marshal.load(Marshal.load(file2))<br>
end<br>
end<br>
end</p>
<p>file.close</p>
<p>ruby 2.0.0dev (2012-05-04 trunk 35535) [i386-mswin32_100]<br>
user system total real<br>
6.068000 0.031000 6.099000 ( 6.334804)<br>
0.530000 0.016000 0.546000 ( 0.573573)</p>
<p>案2)真面目に先読み機構を入れる.</p>
<p> n 要素の Array を load する場合,少なくとも n byte 先読み出来ます(と<br>
いうことを調べるために,始めて Marshal フォーマット *1 を見た).m 番目<br>
まで読み進めた段階で先読みしたバッファが不足した場合,n - m byte 先読み<br>
出来ます.ネストしてると面倒になりますが(この情報をスタックで管理して,<br>
一番先読み可能なものを集めて先読み,みたいな).</p>
<p>*1:<br>
<a href="http://www.ruby-lang.org/ja/old-man/html/Marshal_A5D5A5A9A1BCA5DEA5C3A5C8.html" class="external">http://www.ruby-lang.org/ja/old-man/html/Marshal_A5D5A5A9A1BCA5DEA5C3A5C8.html</a></p>
<p> ちょっと,複雑に過ぎるかも.</p>
<p>--<br>
// SASADA Koichi at atdot dot net</p>
Ruby master - Feature #6440: 引数にIOを渡した場合のMarshal.loadにバッファを持たせたい
https://bugs.ruby-lang.org/issues/6440?journal_id=27124
2012-06-09T12:53:13Z
akr (Akira Tanaka)
akr@fsij.org
<ul></ul><p>2012年5月17日 18:21 Tanaka Akira <a href="mailto:akr@fsij.org" class="email">akr@fsij.org</a>:</p>
<blockquote>
<p>バッファがあると、読みすぎることがあるのではないでしょうか。</p>
<p>読みすぎたぶんを捨ててしまうと、<br>
marshal したデータが複数並んでいるものを読み込む場合に、<br>
動作しなくなってしまうと思います。</p>
</blockquote>
<blockquote>
<p>個人的に最近作っている tb というもので、この動作を利用しているので、<br>
気になるところです。</p>
</blockquote>
<p>気がついたので記録のために書いておきますが、marshal の load が読みすぎないという<br>
性質を process.c でも利用しているようです。</p>
<p>rb_fork_err で、子プロセスの例外を marshal で読み出し、次に errno を読み出し、<br>
エラーメッセージを読み出す、というようなことをやっています。</p>
<pre><code> if ((read(ep[0], &state, sizeof(state))) == sizeof(state) && state) {
io = rb_io_fdopen(ep[0], O_RDONLY|O_BINARY, NULL);
exc = rb_marshal_load(io);
rb_set_errinfo(exc);
}
</code></pre>
<p>#define READ_FROM_CHILD(ptr, len) <br>
(NIL_P(io) ? read(ep[0], (ptr), (len)) : rb_io_bufread(io,<br>
(ptr), (len)))<br>
if ((size = READ_FROM_CHILD(&err, sizeof(err))) < 0) {<br>
err = errno;<br>
}<br>
if (size == sizeof(err) &&<br>
errmsg && 0 < errmsg_buflen) {<br>
ssize_t ret = READ_FROM_CHILD(errmsg, errmsg_buflen-1);<br>
if (0 <= ret) {<br>
errmsg[ret] = '\0';<br>
}<br>
}</p>
<a name="のあたりです"></a>
<h2 >のあたりです。<a href="#のあたりです" class="wiki-anchor">¶</a></h2>
<p>[田中 哲][たなか あきら][Tanaka Akira]</p>
Ruby master - Feature #6440: 引数にIOを渡した場合のMarshal.loadにバッファを持たせたい
https://bugs.ruby-lang.org/issues/6440?journal_id=27165
2012-06-11T22:25:58Z
Glass_saga (Masaki Matsushita)
glass.saga@gmail.com
<ul><li><strong>File</strong> <a href="/attachments/2780">patch2.diff</a> <a class="icon-only icon-download" title="Download" href="/attachments/download/2780/patch2.diff">patch2.diff</a> added</li></ul><p>ささださんの案を元に読み過ぎないような先読み機構を考えてみました。</p>
<p>ささださんが指摘するように、n要素のArrayをm番目まで読んだところでバッファが不足した場合には、<br>
少なくともn - m バイトは先読みできる事が保証されます。</p>
<p>Arrayがネストしている場合には、最も内側にあるArrayに関してはn - m バイト読む事ができますが、<br>
そのひとつ外側のArrayに関しては、最も内側のArrayについて先読みした時点で既に1要素読んでしまっているので、<br>
n - m - 1 バイト先読みする事ができます。それより外側のArrayに関しても同様です。<br>
従って、最も内側のArrayのみn - m バイト先読みする事ができ、それ以外はn - m - 1 バイト先読みする事ができます。</p>
<p>今回は、struct load_argにreadableという「少なくとも何バイト先読みできるか」を表すメンバを追加する事にしました。<br>
r_object0()でtypeがARRAYである場合には、arg->readableにlen - 1を足し、1要素読む毎にデクリメントします。<br>
これは、n - m - 1バイトに対応します。</p>
<p>バッファが不足した場合には、arg->readable + 1バイト先読みできます。<br>
arg->readable + 1とするのは、最も内側のArrayに関してだけn - mバイト先読みする事に相当します。</p>
<p>HashやStructに関しても同様の処理を行なっています。<br>
ただし、これらは1要素に少なくとも2バイトは必要なのでarg->readableには(len - 1) * 2を足し、1要素読む毎に2を引いています。<br>
最も内側のHashやStructに関しては(n - m) * 2バイト、つまりarg->readable + 2バイトまで読めるのですが、<br>
1バイト多く先読みする為だけにr_byteやr_bytes0にtypeを渡す必要もないと思ったので、そこまではやっていません。</p>
<p><a href="/issues/6440">[ruby-dev:45637]</a>と同様のベンチマークを実行したところ、以下の結果となりました。</p>
<p>trunk(r35983)<br>
user system total real<br>
0.560000 0.030000 0.590000 ( 0.601471)</p>
<p>proposed:<br>
user system total real<br>
0.090000 0.010000 0.100000 ( 0.113099)</p>
<p>patchを添付します。</p>
Ruby master - Feature #6440: 引数にIOを渡した場合のMarshal.loadにバッファを持たせたい
https://bugs.ruby-lang.org/issues/6440?journal_id=32957
2012-11-16T15:49:13Z
Glass_saga (Masaki Matsushita)
glass.saga@gmail.com
<ul></ul><p>patch2.diffを適用してコミットしてよいでしょうか?<br>
反対がなければコミットします。</p>
Ruby master - Feature #6440: 引数にIOを渡した場合のMarshal.loadにバッファを持たせたい
https://bugs.ruby-lang.org/issues/6440?journal_id=33349
2012-11-21T00:17:17Z
Anonymous
<ul><li><strong>Status</strong> changed from <i>Assigned</i> to <i>Closed</i></li><li><strong>% Done</strong> changed from <i>0</i> to <i>100</i></li></ul><p>This issue was solved with changeset r37772.<br>
Masaki, thank you for reporting this issue.<br>
Your contribution to Ruby is greatly appreciated.<br>
May Ruby be with you.</p>
<hr>
<ul>
<li>marshal.c: add marshal readahead. marshalized Array, Hash and Struct<br>
have size at least number of its elements, marshal readahead will<br>
read the certain readable length and buffer when it needs more bytes.<br>
marshal readahead prevents many calls to IO#getbyte and IO#read,<br>
then it enables performace improvement.<br>
<a href="/issues/6440">[ruby-dev:45637]</a> [Feature <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: 引数にIOを渡した場合のMarshal.loadにバッファを持たせたい (Closed)" href="https://bugs.ruby-lang.org/issues/6440">#6440</a>]</li>
</ul>