Inconsistent execution speed on the roboRIO?

Today I was trying to determine how long it takes for our motion profiling code to run when I discovered something really weird. The execution time keeps decreasing the more times I run the code. At it’s maximum, it’s nearly two orders of magnitude faster, running in 6ms versus the 500ms when it’s run the first time. I took the measurements like this:

long nanos = System.nanoTime();
TankDriveTrajectory traj = TrajectoryGenerator.generateRotationTank(RobotMap.specs, Math.random() * Math.PI);
traj = TrajectoryGenerator.generateRotationTank(RobotMap.specs, Math.random() * Math.PI);
traj = TrajectoryGenerator.generateRotationTank(RobotMap.specs, Math.random() * Math.PI);
long diff = System.nanoTime() - nanos;
SmartDashboard.putNumber("RobotPathfinder Generation Time (ms)", diff / 1e6);

As you can see, the parameters are randomized each time. Since I wrote the entire library the methods are from, I also know for sure that I didn’t do caching or anything like it. I’m really intrigued and would really like to somehow take advantage of this strange phenomenon. Does anyone have any guesses as to why this happens?

Assuming your library is written entirely in Java, welcome to the wonderful world of Java Just-In-Time (JIT) compilation. Basically the more often it’s run the more is compiled down to native code.

Maybe, if the path generation is implemented in pure Java and has several thousand iterations over the hotspots. IIRC the JIT compiler doesn’t tend to kick in until the same code has been hit 2,000 times.

Yes, the library is written entirely in Java. So does this mean that if I call this function say 20 times in robotInit(), subsequent executions will be sped up until the next time the code restarts?

In general, yes, the speedup you see at that point will continue to persist until the JVM exits. There’s clearly edge cases like if the rest of the code consumes enough memory that the JVM throws away the optimized code…

Thanks! But is there a manual way of invoking the JIT on a piece of code that would produce more… predictable and consistent behavior? Doing so by calling the function multiple times just seems sketchy and unreliable.

Not that I’m aware of. There are many advanced command line options to control the JIT, however: https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html#BABDDFII