Take the 2-minute tour ×

I have some code that profiles Runtime.freeMemory. Here is my code:

package misc;
import java.util.ArrayList;
import java.util.Random;
public class FreeMemoryTest {
private final ArrayList<Double> l;
private final Random r;
public FreeMemoryTest(){
    this.r = new Random();
    this.l = new ArrayList<Double>();
public static boolean memoryCheck() {
    double freeMem = Runtime.getRuntime().freeMemory();
    double totalMem = Runtime.getRuntime().totalMemory();
    double fptm = totalMem * 0.05;
    boolean toReturn = fptm > freeMem;
    return toReturn;
public void freeMemWorkout(int max){
public void workout(int max){
public static void main(String[] args){
    FreeMemoryTest f = new FreeMemoryTest();
    int count = Integer.parseInt(args[1]);
    long startTime = System.currentTimeMillis();
    } else {
    long endTime = System.currentTimeMillis();
    System.out.println(endTime - startTime);

When I run the profiler using -Xrunhprof:cpu=samples, the vast majority of the calls are to the Runtime.freeMemory(), like this:

CPU SAMPLES BEGIN (total = 531) Fri Dec  7 00:17:20 2012
rank   self  accum   count trace method
 1 83.62% 83.62%     444 300274 java.lang.Runtime.freeMemory
 2  9.04% 92.66%      48 300276 java.lang.Runtime.totalMemory

When I run the profiler using -Xrunhprof:cpu=time, I don't see any of the calls to Runtime.freeMemory at all, and the top five calls are as follows:

CPU TIME (ms) BEGIN (total = 10042) Fri Dec  7 00:29:51 2012
rank   self  accum   count trace method
1 13.39% 13.39%  200000 307547 java.util.Random.next
2  9.69% 23.08%       1 307852 misc.FreeMemoryTest.freeMemWorkout
3  7.41% 30.49%  100000 307544 misc.FreeMemoryTest.memoryCheck
4  7.39% 37.88%  100000 307548 java.util.Random.nextDouble
5  4.35% 42.23%  100000 307561 java.util.ArrayList.add

These two profiles are so different from one another. I thought that samples was supposed to at least roughly approximate the results from the times, but here we see a very radical difference, something that consumes more than 80% of the samples doesn't even appear in the times profile. This does not make any sense to me, does anyone know why this is happening?

More on this:

$ java -Xmx1000m -Xms1000m -jar memtest.jar a 20000000 5524
//does not have the calls to Runtime.freeMemory()
$ java -Xmx1000m -Xms1000m -jar memtest.jar f 20000000 9442
//has the calls to Runtime.freeMemory()

Running with freemem requires approximately twice the amount of time as running without it. If 80% of the CPU time is spent in java.Runtime.freeMemory(), and I remove that call, I would expect the program to speed up by a factor of approximately 5. As we can see above, the program speeds up by a factor of approximately 2.

A slowdown of a factor of 5 is way worse than a slowdown of a factor of 2 that was observed empirically, so what I do not understand is how the sampling profiler is so far off from reality.

share|improve this question
add comment

1 Answer

The Runtime freeMemory() and totalMemory() are native calls.

See http://www.docjar.com/html/api/java/lang/Runtime.java.html

The timer cannot time them, but the sampler can.

share|improve this answer
Even if the calls to Runtime.freeMemory() and Runtime.totalMemory() are native calls, their performance is still not consistent between the results from the times profile and the samples profile. In the samples profile, they consume more than 80% of all stack traces. In the times profile, functions that call those native methods do not consume anywhere near 80% of the total time. I don't understand how the two methods of profiling can cause such disparate results. –  zelinka Dec 8 '12 at 7:00
The timer uses byte code injection to profile methods start and end. If the method is native it cant inject the timer code into it. –  Neil Wightman Dec 9 '12 at 10:38
Ignoring the timer issue though there is still a major disparity between what the sampling based profiler says and what the runtimes of the programs say. Using the System.currentTimeMillis() call to get a rough idea of how long something takes, we can clearly see that the calls to Runtime.freeMemory() slow down the program by roughly a factor of 2. Looking at the samples profiler, I would expect the eliminating the Runtime.freeMemory() to result in a much larger speedup, which we do not see. –  zelinka Jan 11 '13 at 19:54
add comment

Your Answer


