Java JIT and RTI Connext DDS Java Application Real-Time Pitfalls
The Java JIT compiler is discussed in the following article:
As the article says, “The Just-In-Time (JIT) compiler is a component of the runtime environment that improves the performance of Java™ applications by compiling bytecodes to native machine code at run time.”
What does that mean to Connext DDS Java developers? Consider the following Java code snippet from a Connext DDS data subscriber application:
public void on_data_available(DataReader reader) {
final StringDataReader stringReader = (StringDataReader) reader;
final SampleInfo sampleInfo = new SampleInfo();
while (true) {
try {
// ------------------------------
// Read the incoming data.
// ------------------------------
final String sample = stringReader.take_next_sample(sampleInfo);
if (sampleInfo.valid_data) {
// Process data here...
}
}
} catch (final RETCODE_NO_DATA noData) {
// No more data to read
break;
} catch (final RETCODE_ERROR e) {
e.printStackTrace();
}
}
}
The on_data_available callback is processed in the Connext DDS receive data thread. The take_next_sample API is executed every time a sample arrives. If samples are being received at a high rate, the Java JVM will note this and after a certain number of executions, the JIT will rebuild the take_next_sample procedure in native byte code to be more efficient. This rebuild can take hundreds of milliseconds. During this time, take_next_sample is blocked. The on_data_available callback and the receive thread are blocked, too. This results in the take_next_sample API taking longer than usual, until JIT finishes its one-time rebuild of take_next_sample.
There are two workarounds. The first is to preemptively execute the Java procedure that may be affected by the JIT a number of times, perhaps 100 times, to invoke the JIT compiler. The second is to use the -Xint Java command-line argument, which disables the JIT.