好吧,这里有几个问题!
1-如何管理短期对象?
如前所述,由于JVM遵循弱代假说,因此可以完美地处理大量短期对象。
请注意,我们所说的是到达主内存(堆)的对象。这并非总是如此。您创建的许多对象甚至都没有留下CPU寄存器。例如,考虑这个for循环
for(int i=0, i<max, i++) {
// stuff that implies i
}
让我们不要考虑循环展开(JVM在您的代码上大量执行的优化)。如果max
等于Integer.MAX_VALUE
,则循环可能需要一些时间才能执行。但是,那i
变量将永远不会逃脱循环块。因此,JVM将把该变量放入CPU寄存器中,定期对其进行递增,但绝不会将其发送回主内存。
因此,如果仅在本地使用,创建数百万个对象并不是什么大问题。它们将在被存储到伊甸园之前被杀死,因此GC甚至不会注意到它们。
2-减少GC的开销是否有用?
像往常一样,这取决于。
首先,您应该启用GC日志记录以清楚了解正在发生的事情。您可以使用启用它-Xloggc:gc.log -XX:+PrintGCDetails
。
如果您的应用程序在GC周期中花费了大量时间,那么可以,请调整GC,否则,可能不值得。
例如,如果您每100毫秒就有一个年轻的GC,耗时10毫秒,则您将10%的时间用在GC上,并且每秒有10个集合(这是很酷的)。在这种情况下,我不会花任何时间进行GC调整,因为那10 GC / s仍会存在。
3-一些经验
在创建大量给定类的应用程序中,我遇到了类似的问题。在GC日志中,我注意到该应用程序的创建速度约为3 GB / s,这太高了(来……每秒3 GB数据?!)。
问题:由于创建过多的对象而导致频繁的GC过多。
就我而言,我附加了一个内存分析器,并注意到一个类代表了我所有对象的很大一部分。我跟踪了这些实例,发现该类基本上是包装在对象中的一对布尔值。在这种情况下,有两种解决方案可用:
我选择第二个,因为它对应用程序的影响最小,并且易于引入。我花了几分钟时间为工厂提供了一个非线程安全的缓存(我不需要线程安全,因为我最终只有四个不同的实例)。
分配速率下降到1 GB / s,年轻GC的频率也下降了(除以3)。
希望能有所帮助!