我的应用程序正在分配大量对象(大约每秒1毫升;大多数对象是大小为80-100的字节数组和相同大小的字符串),我认为它可能是其性能不佳的原因。< / p>
应用程序的工作集只有几十兆字节。分析应用程序显示GC时间可以忽略不计。
但是,我怀疑分配程序可能取决于使用哪个GC,而某些设置可能会使分配更快或者可能对缓存命中率产生积极影响等。
是吗?是这样吗?或者假设垃圾收集本身花费的时间很少,分配性能是否与GC设置无关?答案 0 :(得分:2)
当然,您的表现取决于所使用的分配器。但是您已经对GC进行了分析,并发现这不是一个问题。此外,GC的优势之一是快速分配,代价是收集速度较慢。
我认为你遇到了导致碎片问题的问题,这使得内存访问模式对cpu有问题,因为它可能需要经常使其缓存失效。大多数GC算法都不能以最佳方式回收空间。
由于您的工作集有限且可预测,因此您可能希望使用事先分配的对象池。您可能还希望使用引用计数来避免大部分手动内存管理。从技术上讲,它仍然是GC,但不是GC的常识。
尽管如此,我认为性能不会受到您管理内存的方式的影响,而是您实际使用和访问内存的方式。很可能你的探查者有明确的答案。
答案 1 :(得分:1)
对象分配有两个不同的方面。第一个是找到一个合适的记忆区 - 使用今天的世代型装甲收集器,这通常非常快(大约是机器周期的十分之几)。
第二个是你分配的对象的初始化。由于您在Java中分配的所有内容都已初始化,因此初始化的成本很容易超出分配成本(除了最简单,最小的对象)。还有更多。由于初始化需要写入新对象占用的整个存储区域(例如,如果分配“新字节[1&lt;&lt; 20]”,整个兆字节需要设置为零),这通常也会将内存拉入cpu的缓存,驱逐其他较旧的缓存行(可能属于或不属于当前的“热”工作集)。
如果对每个阵列执行相对较少的处理,则这些影响会严重影响代码的性能。通过反复重复使用相同的数组可以部分避免这种情况,但这通常会使程序逻辑变得更加复杂。通常也不容易确定缓存垃圾是否真的是罪魁祸首。从你的问题中给出的信息很少,我们无法说出来。
答案 2 :(得分:0)
您的VM是否尝试汇集字符串?我曾经听过,IBM的虚拟机做了类似字符串实习但动态(不知道是否真的)也许你的虚拟机正在尝试做额外的工作来构建String内部的内部数据结构。
你是否有机会做byte b[] = new byte[100]; String s = new String(b);
这样的事情?您可能尝试不分配String对象,而是分配一些随机对象,该对象具有对byte []的引用(用于比较)。