我正在尝试对在各种硬件和操作系统平台上运行的JVM进行一些基准测试。我已经创建了一个算法来运用我感兴趣的JVM的各个部分,并打算多次运行这个算法来找到一个不错的平均值。
当我运行基准测试时,我发现第一次运行的时间明显长于后续运行:
132ms
86ms
77ms
89ms
72ms
我怀疑这些类是懒得加载的,在第一次运行时会产生很大的开销。虽然这确实是我认为每个JVM都是独一无二的功能,但此时我并不感兴趣。
是否有标准的命令行选项或属性来急切加载类?还是有人有其他理论吗?
答案 0 :(得分:5)
最简单的方法是忽略第一次运行。 (如果这是有效的事情) 注意:如果您运行相同的代码10,000次,它将进一步编译代码并获得更好的结果,因此您可能希望忽略某些微基准测试的前10K结果。
有些JVM支持急切加载,但我不认为Sun的JVM会这样做。
答案 1 :(得分:5)
如果要强制加载类,请执行以下操作:
public class Main
{
static
{
loadClasses();
}
public static void main(final String[] argv)
{
// whatever
}
private static void loadClasses()
{
final String[] classesToLoad;
// even better, read them from a file and pass the filename to this method
classesToLoad = new String[]
{
"foo.bar.X",
"foo.bar.Y",
}
for(final String className : classesToLoad)
{
try
{
// load the class
Class.forName(className);
}
catch(final ClassNotFoundException ex)
{
// do something that makes sense here
ex.printStackTrace();
}
}
}
}
答案 2 :(得分:4)
Java基准测试的规则#1:方法运行的前15000次(左右)并不感兴趣。
此主题包含一些可靠的建议:How do I write a correct micro-benchmark in Java?
答案 3 :(得分:2)
使用java -XX:+TraceClassLoading
跟踪类的加载。
使用java -XX:+PrintCompilation
跟踪方法何时被JIT。
答案 4 :(得分:1)
一旦加载了类,为避免运行解释器,请使用-Xcomp
(在Sun实现上)仅运行已编译的代码。以这种方式运行普通应用程序可能会非常慢,因为所有代码都必须编译而不仅仅是几件。
答案 5 :(得分:0)
没有标准的命令行选项,因为它不是JVM规范的一部分。延迟类加载是(明确允许的)JVM规范的一部分。在运行之前可以使用Class.forName()
加载您知道的类,但它不会自动传递。
HotSpot编译也会影响前几次运行 - 在编译之前,方法会被解释几次,编译过程需要一些时间。