探查器可以更改递归调用在 Java 中运行的时间吗?
我正在用 Java 重构一些代码,所以我正在计时以确保代码不会变慢。然而,新的重构代码似乎比原始代码花费更多时间。值得注意的是,当我使用分析器运行代码时,新代码明显比旧代码快。主要区别在于旧代码是递归的,而新代码是迭代的。探查器能否对递归代码产生数十万倍的影响,同时仅对迭代代码产生 1.5 倍的影响?
我在 Mac OS X 10.6.6、3 GB RAM、2.4 GHz CPU 上运行,使用默认的 Netbeans 6.9 分析器和 Java 1.6.0__22 64 位服务器。
(这两种方法都有使用 System.currentTimeMillis() 的自计时代码,允许我比较不使用探查器时的时间,但这不会明显影响事情。)
I'm working on refactoring some code in Java, so I I'm timing things to make sure the code doesn't get any slower. However, the new refactored code seems to take more time than the original code. Remarkably, when I run the code with a profiler, the new code is significantly faster than the old code. The primary difference is that the old code is recursive, while the new code is iterative. Can a profiler affect the recursive code by a factor of several hundred thousand while only affecting the iterative code by a factor of 1.5?
I'm running on Mac OS X 10.6.6, 3 GB RAM, 2.4 GHz CPU, using the default Netbeans 6.9 profiler with Java 1.6.0__22 64-Bit Server.
(Both methods have self-timing code using System.currentTimeMillis() to allow me to compare the times when not using a profiler, but this shouldn't affect things noticeably.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
是的。大多数配置文件在方法调用级别进行检测。在递归形式中,分析器必须比迭代形式进行更多的测量。虽然分析器确实尝试从报告的数字中提取开销,但这很难做到可靠。不同的分析器在这方面会更好/更差。
Yes. Most profiles do instrumentation at the level of method invocations. In recursive form, the profiler must take a lot more measurements than in iterative form. While profilers do try to extract their overhead from the reported numbers, this is very difficult to do reliable. Different profilers will be better/worse at this.
是的。代码在分析器下通常运行速度较慢。
因此,您应该比较应用程序的旧/新版本的时间,要么都在探查器下运行,要么都正常运行。
另请注意,分析器实际上可能扭曲性能特征。不同的分析器可能对代码热点的位置存在分歧。因此,在采用正在尝试的优化之前,最好运行/比较应用程序的版本而不进行分析。
这里也有陷阱:
最佳可能的粒度 在某些操作系统上可能是几十毫秒。
如果您不采取措施避免这种情况,您的手动计时可能会包括扭曲的开销,例如 JIT 编译时间和 GC 时间。影响可能非常微妙。
Yes. Code typically runs slower under a profiler.
Therefore, you should compare times of old / new version of your application, either both run under the profiler, or both run normally.
Also be aware that a profiler can actually distort performance characteristics. And different profilers may disagree about where the code hotspots are. So it is a good idea to run/compare versions of your application without profiling before you adopt an optimization that you are trialing.
There are traps here too:
The best possible granularity of
currentTimeMillis()
is 1 millisecond, but on some OSes it might be tens of milliseconds.If you don't take steps to avoid this, your manual timings can include distorting overheads such as the JIT compilation times and the GC times. The effects could be quite subtle.
我想说,如果你想测量速度,就只测量速度,不要分析。它们不是同一件事。检测分析器会给每个函数调用带来大量开销,如果您想要的只是总体速度差异,那么它不会准确,因为您部分测量的是检测本身的成本。
如果您想了解什么花费了时间,这与测量不同。报告行级百分比的挂钟时间堆栈采样分析器(不是仪器)是您的最佳选择。它是否会减慢程序速度并不重要,因为它的目的不是测量速度;而是测量速度。其目的是按百分比找出时间都花在哪里以及原因。如果它或其他东西使程序减慢 10% 或 10 倍,如果它向您显示时间花在哪里,与速度无关,那就没问题了。
我这么说只是因为很多人对这一点感到困惑,并且这种困惑被固化到了很多分析器中。
有关该主题的更多信息.
I would say if you want to measure speed, just measure speed, don't profile. They're not the same thing. Instrumenting profilers put a lot of overhead into each function call, and if all you want is an overall speed difference, it won't be accurate because you're partly measuring the cost of the instrumentation itself.
If you want to find out what is taking the time, that is different from measuring. A wall-clock-time stack-sampling profiler (not instrumentation) that reports line-level percent is your best bet. It doesn't matter if it slows the program down, because it's purpose is not to measure speed; it's purpose is to find out where the time is going and why, on a percentage basis. It would be OK if it or something else slowed the program down by 10%, or 10 times, if it showed you where the time was being taken, independent of speed.
I only say this because lots of people are confused about this point, and the confusion gets solidified into lots of profilers.
More on that subject.