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