A ciekawe czy to śledzi pamięć zaalokowaną ręcznie poza stertą przez aplikację? Tj. wszelkie DirectByteBuffer?
Wydaje mi się, że VM.native_memory tego nie robi, można spojrzeć tak:
- Wyprodukować plik słusznego rozmiaru (np. 768MB), tak by było co mapować i było to w miarę zauważalne, słowem, z rozmachem.
dd if=/dev/zero of=blahz.dat bs=1M count=768
- Wielokrotnie zammapować ten plik używając prostego testu:
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
class Foo {
public static void main(String[] args) throws Exception {
if (args.length != 3) {
System.out.println("Usage : Foo <#iterations> <segment size (in bytes)> <input file name>");
} else {
int nIter = Integer.valueOf(args[0]);
int nSize = Integer.valueOf(args[1]);
String inputFileName = args[2];
System.out.printf("MMAP iterations = %d\nsegment size = %d\nInput filename = %s\n", nIter, nSize, inputFileName);
MappedByteBuffer[] ref = new MappedByteBuffer[nIter];
for (int i = 0; i < nIter; i++)
ref[i] = new RandomAccessFile(inputFileName, "r").getChannel().map(FileChannel.MapMode.READ_ONLY, 0, nSize);
System.out.println("Press return to exit");
System.console().readLine();
}
}
}
- Uruchomić test case (uruchamiam 2, żeby było widać różnicę via : pmap i jcmd VM.native_summary). Rozmiar mmapowanego segmentu=666MB i dwa przebiegy: 10 iteracji i 100 iteracji mmapa (co daje ~6.5GB i ~65GB spodziewanej różnicy).
Dla 10 iteracji:
(Tu korzystam z dobrodziejstw basha $(()) , żeby nie klepać ręcznie tych 666 MB w bajtach)
[pkw@pkwcent ~]$ javac Foo.java
[pkw@pkwcent ~]$ java -XX:NativeMemoryTracking=summary Foo 10 $((666*1024*1024)) blahz.dat
MMAP iterations = 10
segment size = 698351616
Input filename = blahz.dat
Press return to exit
('Press return', to żeby proces powisiał w powietrzu, taki oczywizm, ale może nie dla każdego ;-) )
- W innej sesji podsumowanie via pmap:
[pkw@pkwcent ~]$ pmap -x `jps | grep Foo | awk '{print $1}'` | grep -i total | awk '{print $3/1024/1024 " in GB"}'
9.33921 in GB
oraz via VM.native_memory
[pkw@pkwcent ~]$ jcmd `jps | grep Foo | awk '{print $1}'` VM.native_memory | grep Total | sed 's/KB.*//g' | awk -F\= '{print $2/1024/1024 " in GB"}'
2.18665 in GB
PMAP : 9.33921 in GB
JCMD : 2.18665 in GB
Gołym okiem widać, że VM.native_memory omija niektóre segmenty.
- Dla 100 iteracji mmap.
[pkw@pkwcent ~]$ java -XX:NativeMemoryTracking=summary Foo 100 $((666*1024*1024)) blahz.dat
MMAP iterations = 100
segment size = 698351616
Input filename = blahz.dat
Press return to exit
PMAP : 67.8754 in GB
JCMD : 2.18667 in GB
Morał: PMAP pokazuje te mmapowane segmenty, zaś VM.native_memory wydaje się je olewać.