1

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){
    for(int i = 0; i < max; i++){
        memoryCheck();
        l.add(r.nextDouble());
    }
}
public void workout(int max){
    for(int i = 0; i < max; i++){
        l.add(r.nextDouble());
    }
}
public static void main(String[] args){
    FreeMemoryTest f = new FreeMemoryTest();
    int count = Integer.parseInt(args[1]);
    long startTime = System.currentTimeMillis();
    if(args[0].equals("f")){
        f.freeMemWorkout(count);
    } else {
        f.workout(count);
    }
    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.

4

1 に答える 1

0

ランタイムの freeMemory() と totalMemory() はネイティブ コールです。

http://www.docjar.com/html/api/java/lang/Runtime.java.htmlを参照してください。

タイマーはそれらの時間を計ることはできませんが、サンプラーはできます。

于 2012-12-07T10:26:08.840 に答える