8

Tomcat の下で実行されている Java/jruby webapp があり、実行時にアプリが使用するオブジェクトとメモリの数を分析しています。起動後、クラス「org.jruby.RubyString」に文字列「」のインスタンスが 1,118,000 あることに気付きました。空の文字列だけで使用されるヒープ メモリの総量は 65 MB です。メモリの 15% であるため、これはばかげています。 webapp によって使用されます。空の文字列は、この問題を伴う多くの文字列値の 1 つの例にすぎません。解決したすべての jruby 文字列をインターンできれば、約 130 MB 節約できます。

文字列値が作成されるたびに、値が文字列プールに既に存在するかどうかを確認し、存在する場合は再利用します。Jruby に同じ最適化を持つオプションがあるかどうか疑問に思っていますか? もしそうなら、どうすれば有効にできますか?

Jruby での例:

v1 = "a"
v2 = "a"
puts v1.object_id # => 3352
puts v2.object_id # => 3354

Java での例:

String v1 = "a";
String v2 = "a";

System.out.println(v1.hashCode()); # => 97
System.out.println(v2.hashCode()); # => 97
4

4 に答える 4

5

この背後にある動機は理解できますが、JRuby にはそのような「魔法の」スイッチは実際にはありません ...

Java の背景からすると、文字列を節約したくなりますが、文字列が Java と同じように JRuby で動作するとは期待できません。まず、それらはまったく別のオブジェクトです。RubyStringはどちらかというと Java に近いと言えますStringBuilder

非常に多くの""インスタンスが横たわっているのは確かに無駄ですが、あなたが言及したコードがサードパーティのコードである場合、それについてできることはあまりありません-サルがたくさんパッチを当てたいと思わない限り. ほとんどのインスタンスが由来する場所を特定し、それらをリファクタリングしようとしますが、文字列の保存にはいくつかの「トリッキーな」部分があることを覚えておいてHashください。

{ 'foo' => 'bar' }

これで 3 つのオブジェクトが作成されると思われますが、それは間違いです。実際には の 2 つを作成し'foo'ます。aStringは変更可能であるため ( を除くfrozen?)、それdupは文字列であり、キーfreezeとして使用される場合はs です (Hashこれには十分な理由があります)。

また、「インテリジェントに」リファクタリングすることを忘れないでください。割り当てられたインスタンスを安くしようとして速度を落とさない場合は、変更しているビットをプロファイルします。

于 2012-05-29T12:41:21.670 に答える
2
v1 = v2 = v3 = "a"

Ruby では 3 つではなく、1 つのオブジェクトのみを作成します。

v1 = v2 = v3 = "a" # => "a"
v1.object_id # => 10530560
v2.object_id # => 10530560
v1 << "ll the same" # => "all the same"
v2 # "all the same"

すべての文字列をインターンするような抜本的なことをする前に、これがこの問題に対処する最善の方法であるかどうかを他の tomcat ユーザーに確認します。私は Tomcat や JRuby を使用していませんが、これは最善の方法ではないと強く思っています。

編集「a」から作成されたすべてのオブジェクトが同じオブジェクトである場合、それらの 1 つを変更すると、他のすべての文字列が変更されます。それは副作用の悪夢でしょう。

于 2012-05-27T23:21:02.080 に答える
1

to_symJRuby で String をインターンする唯一の方法は、 orを呼び出しinternて (お互いにエイリアスを設定して)、それらをシンボルにすることです。私の知る限り、他の方法はありません。

これは MRI の動作と一致しています。

sebastien@greystones:~$ rvm ruby-1.9.3-p0
sebastien@greystones:~$ irb
1.9.3p0 :001 > a = "Hello World" 
 => "Hello World" 
1.9.3p0 :002 > b = "Hello World"
 => "Hello World" 
1.9.3p0 :003 > a.object_id
 => 20126420 
1.9.3p0 :004 > b.object_id
 => 19289920 
于 2012-05-28T06:44:23.453 に答える