如何确定哪种方法产生的垃圾最多

时间:2014-01-10 08:30:54

标签: java memory garbage-collection benchmarking heap-memory

我有三个对象:

ClassA classA = new ClassA();
ClassA classB = new ClassA();
ClassA classC = new ClassA();

这些对象中的每一个都有一个名为public void的{​​{1}},它会执行某些操作并按以下方式调用:

run

在每次循环迭代中,每个 classA.run(); classB.run(); classC.run(); 调用都会生成特定数量的垃圾。

如何准确确定每个run生成的垃圾量?

5 个答案:

答案 0 :(得分:3)

通常(如果你可以说OP的用例),你使用profilers / logging来估算分配压力。例如,JRockit Mission Control(适用于JDK 7u40!)可以转储当前的分配率。持续执行run,可能会得到估算每run次呼叫的分配率。确保严格衡量run通话费率,因为此时您正在处理基准测试。以jmh为例。

然而,这很无聊。对于完全不同的东西,我有一个棘手(但有趣!)的建议。由于在大多数现代虚拟机中,包含HotSpot,新对象在线程局部分配缓冲区(TLAB)中线性分配,因此可以获取地址标记,执行run(),然后获取另一个地址标记,减去两个标记,并在通话期间获得TLAB中浪费的空间量。

事实上,在jol中,我们有the funny example doing almost exactly this thing

答案 1 :(得分:2)

有一点知道JVM选项-Xaprof,它报告每个类的全局分配总数。我们创建了一个内部开源“aprof”工具,用于报告每个类别的每种方法的分配率:https://code.devexperts.com/display/AProf/

它通过执行动态字节码修改来执行对象分配跟踪,并尝试平衡性能影响与报告的深度和精度。它确实显着增加了应用程序启动时间,但对运行时性能的影响可以忽略不计,因此我们可以在服务器端组件的生产中使用它。

Aprof精确地收集代码中的所有“新”操作,但不收集每个分配的完整堆栈跟踪。它跟踪每个分配操作的“位置”(类名和方法名),同时提供一种方法将char []的分配(例如,StringBuilder方法)归因于已调用相应StringBuilder方法的实际应用程序代码。它为所有流行的java.lang和java.util类提供了一组合理的默认值,它们在它们内部分配内存,这样你就可以看到你的实际应用程序类作为这些分配的最终位置源。

答案 2 :(得分:0)

您可以尝试使用内置的探查器VisualVM来查看细节。

您可以在名称jvisualvm.exe之类的JDK / bin文件夹中找到它。或者类似的东西。

答案 3 :(得分:0)

double[] heapFreeSizez = new double[5];
for(int i = 0 ; i < 5 ; ++i) {
    heapFreeSizez[i] = 0;
}

heapFreeSizez[0] = (double) Runtime.getRuntime().freeMemory()/1000000.0;
classA.run(); heapFreeSizez[1] = (double) Runtime.getRuntime().freeMemory()/1000000.0;
classB.run(); heapFreeSizez[2] = (double) Runtime.getRuntime().freeMemory()/1000000.0;
classC.run(); heapFreeSizez[3] = (double) Runtime.getRuntime().freeMemory()/1000000.0;
classD.run(); heapFreeSizez[4] = (double) Runtime.getRuntime().freeMemory()/1000000.0;

for(int i = 1 ; i < 5 ; ++i) {
    if(heapFreeSizez[i] - heapFreeSizez[i-1] < 0) {

        System.out.println(i + "_" + "HELP!"); 
    }
}

答案 4 :(得分:0)

您可以使用ThreadMXBean#getThreadAllocatedBytes吗? 它告诉您特定线程分配的内存量。 您需要做的只是衡量差异(并考虑getThreadAllocatedBytes本身产生的大约8-16字节垃圾)