What strategies should be employed to ensure that JVM memory management is always quick?
I run a method periodically, every 10 seconds, via Timer#scheduleAtFixedRate() and the periodic method takes 5 to 50 milliseconds usually but occasionally much longer. The application does not have anything else to do but this periodic method. Sometimes it exceeds 10 seconds. Since the nature of the application does not or should not cause large variability in the elapsed time, I think the variability is due to garbage collection. How can I keep garbage collection well under 10 seconds always?
The periodic method builds up lists and plots points on graphs every 10 seconds for several hours. At the end of the several hour period it does some binary serializations of all data that was collected the whole time.
I tried ending the periodic method with a System.gc() but I still get method runs that take more than 10 seconds. After the 10 second run, it will go back to 5 millisecond elapsed time method runs. Then it will gradually take longer, until there is an elapsed time of about 10 seconds. Then the cycle repeats. I’ve seen other patterns as well.
You might wonder what happens if the method takes longer than the period that is set in scheduleAtFixedRate(). What happens is that the next invocation is delayed (there is no aborting of an in progress method nor an attempt to stick to the schedule by using another thread). If slow runs persist I guess there would simply be a big backlog. Fortunately the long elapsed time runs are just occasional and the majority are just between 5 and 50 milliseconds. Still, I don’t want these long elapsed time runs because they ruin the periodicity.
A quick fix is to change my period to 15 seconds, thereby ensuring the period is greater than the worst case elapsed time. This would only be a work-around. It would be far better to get consistency in garbage collection.
To reduce elapsed times by trading off efficiency use the JVM option -Xincgc on your java invocation command line.