4

我得到了一个 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 编译呢?

我已经尝试使用随机值初始化数据结构(如您在代码中看到的那样),我尝试在测试中返回一个值(如您在代码中看到的那样)并且我尝试使用该course对象,例如调用course.getSize()在上面。但没有任何效果。

4

3 回答 3

7

众所周知,JIT 会以可怕的方式弄乱您的代码,使所有测量结果绝对不可靠。人们挣扎了很多,试图让事情至少在某种程度上正确,但最终写出了JMH 之类的东西。这是一个很棒的工具,可以帮助衡量性能并实际获得有意义的结果。它甚至可以让您避免死代码消除,并拥有大量示例,看看哪些绝对可以帮助您解决问题......

但这是错误的方式。它通常是保密的,但既然你自己找到了正确的方法,我会告诉你的。您可以使用-Xint选项禁用 JIT 。那里。不用谢我。

于 2014-06-27T14:12:07.687 回答
3

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

从一开始就摆脱它。

于 2014-06-27T14:45:10.030 回答
0

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

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

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

于 2014-06-27T13:59:50.647 回答