0

I am iterating over a set of objects in a for-loop and for each object the same graph is generated at one point. I happened to recognize that the graph generation for the first object always has a longer runtime compared to the others.

I suppose that's because of some kind of optimization that's recognized after the first iteration. The problem is that I'd like to compare the runtimes for the objects which should be based on the same conditions for each of them of course.

What kind of optimization is this and can it be disabled?

Edit: Here's a shortened example of the code inside the for-loop:

double startTime = System.currentTimeMillis();
Graph g = new Graph();
for (int entry : entries) {
    graph.addVertex("v" + entry);
}
System.out.println("runtime: " + (System.currentTimeMillis() - startTime) / 1000.0);

Edit: Here are the measurements for the first few loops:

runtime: 0.045  
runtime: 0.001  
runtime: 0.001  
runtime: 0.002  
runtime: 0.002
Hearen
  • 7,420
  • 4
  • 53
  • 63
balderdash
  • 95
  • 10
  • 1
    You should add the code to the question, otherwise you are just goin to get wild guesses. – Juan Mar 21 '19 at 15:44
  • It's a pretty general question I guess, but I added an example. – balderdash Mar 21 '19 at 15:53
  • What can explain this is that the first time the class needs to be loaded by the ClassLoader. – Juan Mar 21 '19 at 16:28
  • I used _-verbose:class_ to show the ClassLoader activity and I think you're right. In the first iteration there are a lot of loaded classes that are not loaded again after that. Do you have a suggestion on how to handle this? I'd like to establish a comparable environment. Can I enforce to load every class beforehand or something like that? – balderdash Mar 21 '19 at 16:49
  • Discard the first iteration – Juan Mar 21 '19 at 17:01
  • A bit of a hack imo, but it's a workaround and I'll do that for now. Thanks for your help. – balderdash Mar 21 '19 at 17:46
  • It isn't a hack, the first iteration is nor running under the same conditions the rest of the iterations do. So i f you want an average of all iterations you should include it. If you consider the first iteration to be out of scope, you just leave it out. – Juan Mar 21 '19 at 18:02
  • There are a lot of things going on, which all have the effect of making subsequent executions faster. First, the loading, then execution starts interpreted before the code gets compiled the first time, then it may get compiled a second time utilizing the information gathered during the first executions for optimizations. You should read the answers to [How do I write a correct micro-benchmark in Java?](https://stackoverflow.com/q/504103/2711488) or even consider your question a duplicated of that question… – Holger Mar 22 '19 at 08:13
  • How many entries do you have? As @Holger suggested your code may transition from interpreted to JIT-compiled code during the first iteration. There are typically ~10,000 iterations needed for JIT to kick in and compile "hot method" into native code. – Juraj Martinka Mar 22 '19 at 18:25
  • I have less than 100 entries, so that shouldn't be the case. It's fixed now using the workaround of discarding the first iteration. I suppose that it was the extra time used for class loading that lead to a longer runtime there. – balderdash Mar 25 '19 at 10:31

2 Answers2

0

It could be due to C1/C2 optimization. Running in interpreter code will disable optimization. Run using -Xint. Note that running in that mode will have performance impact for entire application.

Fairoz
  • 1,616
  • 13
  • 16
  • I tried that, but it only increases the runtime of every iteration, the difference between the first and the following iterations stays the same. As said, I suppose it has to do with the class loader activity during the first iteration. – balderdash Mar 25 '19 at 10:35
0

I used -verbose:class to show the ClassLoader activity. In the first iteration there are a lot of loaded classes that are not loaded again after that. As suggested by @Juan, I am simply discarding the first iteration now as a workaround. After that all the classes are loaded and each iteration is running under the same conditions.

balderdash
  • 95
  • 10