我们有一个运行在tomcat下的java/jruby webapp,我一直在分析app在运行时的对象数和内存使用情况。我注意到启动后类“org.jruby.RubyString”有 1,118,000 个字符串“”实例,仅空字符串使用的堆内存总量为 65mb,这对我来说很荒谬,因为它是内存的 15%由网络应用程序使用。空字符串只是许多存在此问题的字符串值的一个示例,如果我可以实习我计算出的所有 jruby 字符串,我可以节省大约 130mb。
我知道在 Java 中,每次创建一个字符串值时,它都会检查该值是否已存在于字符串池中,如果存在,则重用它。我想知道 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
最佳答案
我理解这背后的动机,但 JRuby 中确实没有这种“神奇”的开关......
从 Java 背景来看,节省字符串感觉很诱人,但您不能期望字符串在 JRuby 中的行为方式与它们在 Java 中的行为方式相同。首先,它们是完全不同的对象。我什至可以说 Ruby String
更像是 Java StringBuilder
。
周围有这么多 ""
实例当然是一种浪费,但是如果您提到的代码是第三方代码,那么您无能为力 - 除非您觉得自己像个猴子修补了很多。我会尝试确定大多数实例的来源并重构它们 - 但请记住在保存字符串时有一些“棘手”的部分,例如使用哈希
:
{ 'foo' => 'bar' }
您可能会猜测这会创建 3 个对象,但您错了;它实际上创建了两个 'foo'
。因为 String
是可变的(除非 frozen?
)它dup
字符串和 freeze
当用作Hash
键(这是有充分理由的)。
另外请记住“智能地”重构 - 如果您不通过尝试降低分配实例的成本来减慢速度,请分析您正在更改的位。
关于java - 有没有办法让 Jruby 运行时实习所有字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10746737/