是否有人曾经使用秒表基准测试,或者应该始终使用性能工具?有什么好的免费 Java 工具吗?你用什么工具?
为了澄清我的担心,秒表基准测试容易由于操作系统调度而出错。在给定的程序运行时,操作系统可能会在计时函数的中间安排另一个(或多个)进程。在 Java 中,如果您试图为一个线程化应用程序计时,情况会更糟糕一些,因为 JVM 调度程序在这种情况下会产生更多的随机性。
在进行基准测试时,如何解决操作系统调度问题?
我总是使用秒表基准,因为它是如此容易。不过对我来说,结果不需要非常精确。如果你需要准确的结果,那么你不应该使用秒表基准。
我不认为秒表基准测试是太可怕的,但如果你能进入 Solaris 或 OS X 机器,你应该看看 DTrace。我用它来获得一些关于应用程序计时的重要信息。
秒表基准测试是很好的,只要您度量 够了迭代是有意义的。通常,我需要一些单位数字秒的总经过时间。否则,您的结果很容易受到日程安排和流程中的其他 O/S 中断的严重影响。
为此,我使用了一些很久以前构建的静态方法,它们基于 System.currentTimeMillis()。
System.currentTimeMillis()
对于分析工作,我已经使用 JProfiler数年,并发现它非常好。我最近浏览了 YourKit,它从网站上看起来很棒,但是我个人完全没有使用过它。
为了回答关于调度中断的问题,我发现重复运行直到达到一致性/观察到的结果在实践中可以从进程调度中剔除异常结果。我还发现,线程调度对于5到30秒的运行没有实际影响。最后,根据我的经验,超过几秒钟的阈值后,调度对结果的影响可以忽略不计——我发现5秒钟的运行与5分钟的时间/迭代运行的平均值一致。
您可能还需要考虑预先运行大约10,000次测试代码来“预热”JIT,这取决于您期望测试代码在现实生活中运行的次数。
分析器提供了更详细的信息,有助于诊断和修复性能问题。
在实际测量方面,秒表时间是用户注意到的,所以如果你想验证事情是在可接受的限制,秒表时间是好的。
但是,当您想要实际修复问题时,分析器可能非常有帮助。
我今天运行了一个程序,它从一堆 dBase 文件中搜索和收集信息,运行时间刚刚超过 一个小时。我看了一下代码,对瓶颈是什么做了一个有根据的猜测,对算法做了一个小小的改进,然后重新运行了程序,这次它是在 2.5分钟中完成的。
我不需要任何奇特的分析工具或基准测试套件来告诉我新版本是一个显著的改进。如果我需要进一步优化运行时间,我可能会做一些更复杂的分析,但这是没有必要的。我发现在很多情况下,这种“秒表基准测试”是一种可以接受的解决方案,在这些情况下,使用更高级的工具实际上会更费时间。
我经常这么做。我更愿意使用侧写器,但与我合作的领域特定语言供应商却不提供。
它是完全有效的,只要你测量足够大的时间间隔。我将执行您打算测试的20-30次运行,以便总运行时间超过1秒。我注意到,基于 System.currentTimeMillis ()的时间计算往往是0ms 或30ms; 我认为没有比这更精确的了。如果您确实需要测量一个小的时间间隔,您可能想尝试 System.nanTime () :
毕竟,它可能是第二流行的基准测试形式,仅次于“无表基准测试”——我们说“这个活动看起来很慢,那个活动看起来很快。”
通常最需要优化的是那些干扰用户体验的东西——这通常取决于你执行操作的频率,以及同时发生的其他事情。其他形式的基准测试通常只是帮助集中在这些方面。
分析器可能会妨碍计时,因此我将使用秒表计时的组合来确定整体性能问题,然后使用分析器来计算时间花费在哪里。根据需要重复该过程。
我认为一个关键问题是手术的复杂性和时间长度。
我有时甚至使用物理秒表测量来判断计算是否需要花费分钟、小时、天甚至几周的时间(我正在使用一个应用程序,其中几天的运行时间并不是闻所未闻的,即使秒和分钟是最常见的时间跨度)。
然而,对计算机上任何类型的时钟系统的调用(如链接文章中提到的 java milis 调用)所提供的自动化,显然优于手动查看某些东西运行多长时间。
分析器在工作时是很好的,但是我在将它们应用到我们的应用程序时遇到了问题,这通常涉及动态代码生成、 DLL 的动态加载,以及在我的应用程序的两种内置的实时编译脚本语言中执行的工作。它们通常仅限于假设一种单一的源语言,以及对复杂软件的其他不切实际的期望。
秒表实际上是最好的基准!
真正的端到端用户响应时间是真正重要的时间。
使用可用的工具并不总是可以获得这些时间,例如大多数测试工具不包括浏览器渲染页面所需的时间,所以一个过于复杂的带有拙劣编写的 css 的页面将显示测试工具的次秒响应时间,但是,5秒加上用户的响应时间。
这些工具对于自动化测试和问题确定非常有用,但是不要忽视您真正想要度量的内容。
您需要测试实际的迭代次数,因为根据测试时机的方式,您将得到不同的答案。如果只执行一次操作,那么采用多次迭代的平均值可能会产生误导。如果您想知道在 JVM 预热之后所花费的时间,您可能会运行许多(例如10,000)迭代,这些迭代不包括在计时中。
我还建议您使用 System.nanoTime(),因为它更准确。如果您的测试时间大约是10微秒或更少,您不希望太频繁地调用它,否则它可能会改变您的结果。(例如:。如果我正在测试5秒钟,并且我想知道这是什么时候开始的,那么如果我知道一个迭代非常快,那么我每1000次迭代只能得到 nanTime)
System.nanoTime()
够久了的基准测试是一个系统,它代表了你将要使用的机器。如果您的操作系统使应用程序变慢,那么这应该是结果的一部分。
没有必要说,如果我没有操作系统,我的程序会更快。
如果您正在使用 Linux,您可以使用工具,如 numactl,chrt和 taskset来控制如何使用 CPU 和调度。
Linux
numactl
chrt
taskset