Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 可靠地测量JVM分配_Performance_Kotlin_Jmh - Fatal编程技术网

Performance 可靠地测量JVM分配

Performance 可靠地测量JVM分配,performance,kotlin,jmh,Performance,Kotlin,Jmh,我有两个相同算法的实现。我想验证它们中的任何一个是否使用了超出必要的内存,或者换句话说,它们是否分配了完全相同数量的对象 我当前的解决方案是通过threadMXBean.getThreadAllocatedBytes(threadId)测量过程前后分配的字节数,并将其用作内存占用的近似值 问题是这个方法是不稳定的,也就是说,有时它返回的数字比它应该返回的要大得多。它特别显示在不分配对象的算法上。一个有问题的例子是对int[]求和的方法 实际代码(Kotlin): 有更好的解决办法吗 (我不知道如

我有两个相同算法的实现。我想验证它们中的任何一个是否使用了超出必要的内存,或者换句话说,它们是否分配了完全相同数量的对象

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

问题是这个方法是不稳定的,也就是说,有时它返回的数字比它应该返回的要大得多。它特别显示在不分配对象的算法上。一个有问题的例子是对
int[]
求和的方法

实际代码(Kotlin):

有更好的解决办法吗


(我不知道如何使用JMH实现这一点,但这是一个非常接近的主题)

我当前的解决方案是通过多次运行收集统计数据:

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")
}

JMH有
-prof gc
分析器,它应该能够准确地进行分配分析。尽管它在封面下使用了相同的
ThreadMXBean
,但它可以过滤掉预热效果,并在多次
@Benchmark
调用中平均打嗝。典型的错误在0.001字节/op范围内。

与问题没有直接关系,但我似乎不明白
Thread.currentThread().id
block
execution之后会发生什么变化?@miensol问得好,我想不会。编辑后,是否可以将其嵌入到单元测试中?(最好不用解析bash输出)嗯,是的,您可以使用JMH API运行JMH基准测试,并解析出探查器结果。我只是对“我知道JMH不会那样做”的反应——它会这样做。:)但是,为了单元测试,最好理解原始代码出现问题的原因。我想说的是,您需要过滤掉
block()
ThreadMXBean
方法的最初几次调用,以便JVM可以先进行惰性初始化,而无需进行分析。哦,很抱歉这样的措辞,我希望现在更好。请你看看我做了什么(另一个答案),以确认这是接近什么应该工作。基本上,我跳过前几次,然后选择最常用的度量。我认为选择分布“模式”很好。
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")
}