可靠地测量JVM分配

问题描述 投票:3回答:2

我有两个相同算法的实现。我想验证它们中的非内存使用的内存多于必要的内存,换句话说,它们分配的内容数量完全相同。

我目前的解决方案是通过threadMXBean.getThreadAllocatedBytes(threadId)测量程序之前和之后分配的字节数,并将其用作内存占用的近似值。

问题是这种方法不稳定,e.i。有时它会返回比它应该更多的数字。它特别显示了不分配对象的算法。一个有问题的例子是对int[]求和的方法。

实际代码(Kotlin):

class MemAllocationTest {

    private val threadMXBean = (ManagementFactory.getThreadMXBean() as? com.sun.management.ThreadMXBean)
            ?: throw RuntimeException("Runtime does not support com.sun.management.ThreadMXBean")

    /**
     * May run [block] several times
     * */
    private inline fun measureAllocatedBytes(block: () -> Unit): Long {
        val threadId = Thread.currentThread().id

        val before = threadMXBean.getThreadAllocatedBytes(threadId)
        block()
        val after = threadMXBean.getThreadAllocatedBytes(threadId)

        return after - before
    }

....

有更好的解决方案吗?

(我不知道如何用JMH做到这一点,但恕我直言这是一个非常接近的主题)

performance kotlin jmh
2个回答
3
投票

JMH有-prof gc分析器,它应该是准确的分配分析。虽然它在掩护下使用相同的ThreadMXBean,但它可以过滤掉预热效果,并在多个@Benchmark调用中平均打嗝。那里的典型错误在0.001字节/ op之内。


0
投票

我目前的解决方案是通过多次运行收集统计信息:

private inline fun stabiliseMeasureAllocatedBytes(block: () -> Unit): Long {
    val runs = List(7) { measureAllocatedBytes(block) }
    val results = runs.drop(2) // skip warm-up

    val counts = results.groupingBy { it }.eachCount()
    val (commonResult, commonCount) = counts.entries.maxBy { (result, count) -> count }!!

    if (commonCount >= results.size / 2)
        return commonResult
    else
        throw RuntimeException("Allocation measurements vary too much: $runs")
}
© www.soinside.com 2019 - 2024. All rights reserved.