Java Profiling:私有属性 Getter 具有较大的基准时间
Posted
技术标签:
【中文标题】Java Profiling:私有属性 Getter 具有较大的基准时间【英文标题】:Java Profiling: Private Property Getter has Large Base Time 【发布时间】:2009-03-27 16:00:23 【问题描述】:我正在使用 TPTP 来分析一些运行缓慢的 Java 代码,我遇到了一些有趣的事情。我的一个私有属性 getter 在执行时间分析结果中具有很大的基准时间值。公平地说,这个属性被调用了很多次,但我从来没有想到这样的属性会花费很长时间:
public class MyClass
private int m_myValue;
public int GetMyValue()
return m_myValue;
好的,显然类中还有更多内容,但是正如您所见,当调用 getter 时没有其他任何事情发生(只返回一个 int)。给你一些数字:
大约 30% 的运行调用是 在吸气剂上(我正在努力减少 这个) 大约 25% 的基准时间 运行在这个 getter 中花费 平均基准时间为 0.000175s为了比较,我在不同的类中有另一个方法使用这个 getter:
private boolean FasterMethod(MyClass instance, int value)
return instance.GetMyValue() > m_localInt - value;
平均基准时间要低得多,为 0.000018 秒(低一个数量级)。
这里有什么问题?我认为有些东西我不明白或我遗漏了一些东西:
-
返回本地原语是否真的比返回计算值花费更长的时间?
我应该查看基准时间以外的指标吗?
这些结果是否具有误导性,我需要考虑使用其他分析工具吗?
编辑1:根据下面的一些建议,我将该方法标记为最终方法并重新运行测试,但得到了相同的结果。
编辑 2:我安装了 YourKit 的演示版来重新运行我的性能测试,YourKit 结果看起来更接近我的预期。我将继续测试 YourKit 并报告我的发现。
编辑 3: 更改为 YourKit 似乎解决了我的问题。我能够使用 YourKit 来确定我的代码中的实际慢点。下面有一些优秀的 cmets 和帖子(适当地赞成),但我接受第一个建议 YourKit 为“正确”的人。 (我与 YourKit 没有任何关联/YMMV)
【问题讨论】:
听起来有误导性 - 我会尝试第二个分析器来看看... 不是很相关,但是Java编码标准是方法名以小写开头,不要在变量前加“m_”。 您也可以尝试使用 YourKit 进行分析,这需要付费,但有 14 天的免费试用期。 如果你能用 Netbeans 来做,试一试,它是免费的(而且分析器很好,YourKit 也是,我都用过)。 【参考方案1】:如果可能,请尝试使用另一个分析器(Netbeans 可以很好地工作)。根据您的代码设置方式,这可能很难做到。
就像许多其他工具一样,不同的分析器可能会产生不同的信息。
返回一个本地原语真的比返回一个原语花费更长的时间吗? 计算值?
返回实例变量比返回局部变量(取决于 VM)花费的时间更长。您拥有的 getter 很简单,因此它应该被内联,因此它变得与访问公共实例变量一样快(同样,它比访问局部变量慢)。
但您没有本地值(方法中的本地含义,而不是类中的本地含义)。
“本地”到底是什么意思?
我应该查看基准时间以外的指标吗?
我没有使用过 Eclipse 工具,所以我不确定它是如何工作的……如果它是一个跟踪或采样分析器,它可能会有所不同(对于这样的事情,两者可以给出不同的结果)。
这些结果是否具有误导性,我需要考虑其他一些 分析工具?
我会考虑另一种工具,只是看看结果是否相同。
基于 cmets 编辑:
如果它是一个采样分析器,那么本质上,每个“n 时间单位”都会对程序进行采样以查看程序的位置。如果您调用一种方法的次数多于另一种方法,它将显示为在被调用次数较多的方法中(很可能该方法正在运行)。
跟踪分析器将代码添加到您的程序(称为检测的过程)以从本质上记录正在发生的事情。
跟踪分析器速度较慢但更准确,它们还需要更改程序(检测过程),这可能会引入错误(不是我听说过它发生...但我相信它至少在他们正在开发探查器)。
采样分析器更快但不太准确(它们只是猜测一行代码的执行频率)。
因此,如果 Eclipse 使用采样分析器,您可能会看到您认为奇怪的行为。更改为跟踪分析器将显示更准确的结果。
如果 Eclipse 使用跟踪分析器,那么更改分析器应该会显示相同的结果(但是新的分析器可能会让您更清楚地了解正在发生的事情)。
【讨论】:
你是对的:我打错了。我应该说“实例”变量,而不是“本地”变量。我的部分困惑来自 FasterMethod() 方法。我同时使用本地(传入)和实例变量,但它比使用实例变量更快(根据 TPTP)。 四处挖掘我认为 Eclipse 使用了采样分析器。听起来它也可以通过插件或选项(对不起,不是 Eclipse 用户)来执行跟踪。【参考方案2】:听起来确实有点误导 - 也许分析器正在删除一些优化?
只是为了好玩,尝试将方法设为 final,这将更容易内联。这很可能是属性和 FasterMethod 之间的区别。在实际使用中,HotSpot 甚至会内联虚拟方法,直到它们第一次被覆盖 (IIRC)。
编辑:回应 Brian 的评论:是的,通常的情况是,制作最终的东西不会提高性能(尽管它在设计方面可能是一件好事 :) 因为 Hotspot 通常会根据它是否被覆盖来确定它是否可以内联。我的意思是这个分析器可能搞砸了。
编辑:我现在已经设法重现 HotSpot “撤消”尚未扩展的类(或尚未覆盖的方法)的优化的方式。对于服务器虚拟机来说,这比客户端更难做到,但我已经做到了:)
public class Test
public static void main(String[] args)
throws Exception
final long iterations = 1000000000L;
Base b = new Base();
// Warm up Hotspot
time(b, 1000);
// Before we load Derived
time(b, iterations);
// Load Derived and use it quickly
// (Just loading is enough to make the client VM
// undo its optimizations; the server VM needs more effort)
Base d = (Base) Class.forName("Derived").newInstance();
time(d, 1);
// Time it again with Base
time(b, iterations);
private static void time(Base b, long iterations)
long total = 0;
long start = System.currentTimeMillis();
for (long i = 0; i < iterations; i++)
total += b.getValue();
long end = System.currentTimeMillis();
System.out.println("Time: " + (end-start));
System.out.println("Total: " + total);
class Base
public int getValue() return 1;
class Derived extends Base
@Override
public int getValue() return 2;
【讨论】:
如果 final 有所作为我会很感兴趣。理论上,JVM 可以安全地缓存该值,而不必读取(慢速)主内存。 在此处查看 Brian Goetz 的信息。最终确定 - ibm.com/developerworks/java/library/j-jtp04223.html 仅供参考 - 我将该方法标记为最终方法并重新运行测试,但得到了相同的结果。 对。呃,好吧。我正在编辑我的答案,并举了一个无论如何都会产生影响的例子,只是因为它很有趣:) 是的,Hotspot 可以内联事物,然后如果加载的类破坏了内联,则撤消内联。 C++ 不能(轻松地)内联虚拟方法(有些编译器显然可以做到这一点,但会占用运行时使用量)。未来 Java 的一个很好的例子是缓慢的辩论:-)【参考方案3】:这听起来很奇怪。您不会错误地调用了覆盖方法,是吗?
我很想下载a demo version of YourKit。设置起来很简单,它应该可以指示真正发生的事情。如果 TPTP 和 YourKit 都同意,那么就会发生一些奇怪的事情(我知道这没有多大帮助!)
【讨论】:
好问题,但没有覆盖方法。【参考方案4】:曾经对这类方法的性能产生很大影响的东西(尽管这可能在某种程度上是历史性的)是调用方法的大小可能是一个问题。 HotSpot(和严肃的竞争对手)很乐意内联小方法(有些可能会在同步/最终尝试时窒息)。但是,如果调用方法很大,则可能不会。这对于旧版本的 HotSpot C1/客户端来说尤其成问题,它的寄存器分配算法非常糟糕(现在它的算法既非常好又快)。
【讨论】:
以上是关于Java Profiling:私有属性 Getter 具有较大的基准时间的主要内容,如果未能解决你的问题,请参考以下文章
Profiling Java Application with Systemtap