由于JIT编译,Caliper基准测试失败

时间:2014-06-25 12:34:24

标签: java microbenchmark caliper

我得到了Caliper基准测试,看起来像这样:

public Course timeCourseCreation( int i ) {

  return createCourse( i );
}

public Course createCourse( int t ) {

  Course course = new Course();

  for ( int i = 0 + t; i < this.students + t; i++ ) {
    Student student = new Student();
    student.setAge( ( int ) ( 100 * Math.random() ) + t );
    student.setName( UUID.randomUUID().toString() );
    course.getStudents().add( student );
  }

  for ( int i = 0 + t; i < this.courses + t; i++ ) {
    Topic topic = new Topic();
    topic.setDescription( UUID.randomUUID().toString() );
    topic.setDifficulty( ( int ) ( 10 * Math.random() ) + t );
    topic.setName( UUID.randomUUID().toString() );
    topic.setRating( ( int ) ( 10 * Math.random() ) + t );
    course.getTopics().add( topic );
  }

  return course;
}

所以,我有一个创建数据结构(createCourse(...))的方法,我想测量创建这个结构所需的时间。

但是,当我运行基准测试时,我得到以下异常:

Failed to execute java -cp C:\Users\tuhrig\workspace\XmlVsJson\target\classes;C:\Users\tuhrig\.m2\repository\javax\xml\bind\jaxb-api\2.2.11\jaxb-api-2.2.11.jar;C:\Users\tuhrig\.m2\repository\com\google\code\gson\gson\2.2.4\gson-2.2.4.jar;C:\Users\tuhrig\.m2\repository\com\google\caliper\caliper\0.5-rc1\caliper-0.5-rc1.jar;C:\Users\tuhrig\.m2\repository\com\google\code\findbugs\jsr305\1.3.9\jsr305-1.3.9.jar;C:\Users\tuhrig\.m2\repository\com\google\guava\guava\11.0.1\guava-11.0.1.jar;C:\Users\tuhrig\.m2\repository\com\google\code\java-allocation-instrumenter\java-allocation-instrumenter\2.0\java-allocation-instrumenter-2.0.jar;C:\Users\tuhrig\.m2\repository\asm\asm\3.3.1\asm-3.3.1.jar;C:\Users\tuhrig\.m2\repository\asm\asm-analysis\3.3.1\asm-analysis-3.3.1.jar;C:\Users\tuhrig\.m2\repository\asm\asm-commons\3.3.1\asm-commons-3.3.1.jar;C:\Users\tuhrig\.m2\repository\asm\asm-tree\3.3.1\asm-tree-3.3.1.jar;C:\Users\tuhrig\.m2\repository\asm\asm-util\3.3.1\asm-util-3.3.1.jar;C:\Users\tuhrig\.m2\repository\asm\asm-xml\3.3.1\asm-xml-3.3.1.jar com.google.caliper.InProcessRunner --warmupMillis 3000 --runMillis 1000 --measurementType TIME --marker //ZxJ/ -Dbenchmark=CourseCreation de.tuhrig.Benchmark
starting Scenario{vm=java, trial=0, benchmark=CourseCreation}
[caliper] [starting warmup]
[caliper] [starting measured section]
[caliper] [done measured section]
[caliper] [starting measured section]
...
Error: Doing 2x as much work didn't take 2x as much time! Is the JIT optimizing away the body of your benchmark?
...
An exception was thrown from the benchmark code.
com.google.caliper.ConfigurationException: Failed to execute java -cp C:\Users\tuhrig\workspace\XmlVsJson\target\classes;C:\Users\tuhrig\.m2\repository\javax\xml\bind\jaxb-api\2.2.11\jaxb-api-2.2.11.jar;C:\Users\tuhrig\.m2\repository\com\google\code\gson\gson\2.2.4\gson-2.2.4.jar;C:\Users\tuhrig\.m2\repository\com\google\caliper\caliper\0.5-rc1\caliper-0.5-rc1.jar;C:\Users\tuhrig\.m2\repository\com\google\code\findbugs\jsr305\1.3.9\jsr305-1.3.9.jar;C:\Users\tuhrig\.m2\repository\com\google\guava\guava\11.0.1\guava-11.0.1.jar;C:\Users\tuhrig\.m2\repository\com\google\code\java-allocation-instrumenter\java-allocation-instrumenter\2.0\java-allocation-instrumenter-2.0.jar;C:\Users\tuhrig\.m2\repository\asm\asm\3.3.1\asm-3.3.1.jar;C:\Users\tuhrig\.m2\repository\asm\asm-analysis\3.3.1\asm-analysis-3.3.1.jar;C:\Users\tuhrig\.m2\repository\asm\asm-commons\3.3.1\asm-commons-3.3.1.jar;C:\Users\tuhrig\.m2\repository\asm\asm-tree\3.3.1\asm-tree-3.3.1.jar;C:\Users\tuhrig\.m2\repository\asm\asm-util\3.3.1\asm-util-3.3.1.jar;C:\Users\tuhrig\.m2\repository\asm\asm-xml\3.3.1\asm-xml-3.3.1.jar com.google.caliper.InProcessRunner --warmupMillis 3000 --runMillis 1000 --measurementType TIME --marker //ZxJ/ -Dbenchmark=CourseCreation de.tuhrig.Benchmark
    at com.google.caliper.Runner.measure(Runner.java:309)
    at com.google.caliper.Runner.runScenario(Runner.java:229)
    at com.google.caliper.Runner.runOutOfProcess(Runner.java:378)
    at com.google.caliper.Runner.run(Runner.java:97)
    at com.google.caliper.Runner.main(Runner.java:423)
    at de.tuhrig.CaliperRunner.main(CaliperRunner.java:22)

该异常告诉我基准测试由于JIT编译而失败。 那么,我怎样才能阻止JIT编译呢?

我已经尝试使用随机值初始化数据结构(正如您在代码中看到的那样),我尝试在测试中返回一个值(正如您在代码中看到的那样)并且我尝试使用{{ 1}}对象,例如在其上拨打course。但没有任何作用。

3 个答案:

答案 0 :(得分:7)

众所周知,JIT会以可怕的方式搞乱您的代码,使得所有测量结果绝对不可靠。人们挣扎很多,试图让事情至少在某种程度上正确,但最终还是要编写像JMH这样的东西。这是一个很好的工具,可以帮助衡量性能,并实际获得有意义的结果。它甚至可以让你avoid dead code elimination并拥有大量的samples,看看这肯定会帮助你解决问题......

但这是错误的方式。它通常保密,但既然你已经找到了正确的方法,我会告诉你。您可以使用-Xint option禁用JIT。那里。无需感谢我。

答案 1 :(得分:3)

您无法对依赖于UUID生成的内容进行基准测试。从大多数操作系统获取随机信息取决于操作系统状态,随机池的状态等。 我发现这会引起不可靠的行为。

首先摆脱它。

答案 2 :(得分:0)

你的Benchmark不是很有用:你主要测试Math.random和UUID的速度。此外,它“只是”分配一个PoJo(看起来像),你会从中得到什么结果,另外它可能会或可能不会受到GC的约束。

JIT不是您的问题,因为您希望您的代码加快速度。我不确定问题出在哪里,因为您返回创建的对象时JIT可能无法抑制代码(除非Caliper无法正常工作)。

我怀疑数学随机或GC会导致不稳定的结果。您可以尝试使用JMH,但它不会使测量更有用。