2021-2-25:對於 Java MMAP,如何查看文件映射髒頁,如何統計MMAP的內存大小?

咱們寫一個測試程序:java

public static void main(String[] args) throws Exception {
    RandomAccessFile randomAccessFile = new RandomAccessFile("./FileMmapTest.txt", "rw");
    FileChannel channel = randomAccessFile.getChannel();
    MappedByteBuffer []mappedByteBuffers = new MappedByteBuffer[5];

    //開5個相同文件的MappedByteBuffer,可是實際機器內存只有8G
    mappedByteBuffers[0] = channel.map(FileChannel.MapMode.READ_WRITE, 0, 2 * 1024 * 1024 * 1024 - 1);
    mappedByteBuffers[1] = channel.map(FileChannel.MapMode.READ_WRITE, 0, 2 * 1024 * 1024 * 1024 - 1);
    mappedByteBuffers[2] = channel.map(FileChannel.MapMode.READ_WRITE, 0, 2 * 1024 * 1024 * 1024 - 1);
    mappedByteBuffers[3] = channel.map(FileChannel.MapMode.READ_WRITE, 0, 2 * 1024 * 1024 * 1024 - 1);
    mappedByteBuffers[4] = channel.map(FileChannel.MapMode.READ_WRITE, 0, 2 * 1024 * 1024 * 1024 - 1);

    for (int j = 0; j < 2*1024*1024*1024 - 1; j++) {
        mappedByteBuffers[0].put("a".getBytes());
    }
    TimeUnit.SECONDS.sleep(1);
    byte []to = new byte[1];

    for (int j = 0; j < 2*1024*1024*1024 - 1; j++) {
        mappedByteBuffers[1].get(to);
        mappedByteBuffers[2].get(to);
        mappedByteBuffers[3].get(to);
        mappedByteBuffers[4].get(to);
    }

    while(true) {
        TimeUnit.SECONDS.sleep(1);
    }
}

等到程序運行到最後的死循環的時候,咱們來看top -c的結果:linux

KiB Mem :  7493092 total,   147876 free,  3891680 used,  3453536 buff/cache
KiB Swap:        0 total,        0 free,        0 used.  2845100 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+                                                                                                                                                                                              
25458 zhangha+  20   0 14.147g 8.840g 8.599g S   0.0  124   2:33.16 java

能夠觀察到很是有意思的現象,這個進程佔用了124%的內存,實際上Swap爲0。總佔用也沒到100%。這是爲何呢?編程

咱們來看下這個進程的smaps文件,這裏進程號是25485,咱們映射的文件是FileMmapTest.txt:微信

$ grep -A 11 FileMmapTest.txt  /proc/25458/smaps
7fa870000000-7fa8f0000000 rw-s 00000000 ca:01 25190272                   /home/zhanghaoxin/FileMmapTest.txt
Size:            2097152 kB
Rss:             2097152 kB
Pss:              493463 kB
Shared_Clean:    2097152 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         0 kB
Referenced:      2014104 kB
Anonymous:             0 kB
AnonHugePages:         0 kB
Swap:                  0 kB
--
7fa8f0000000-7fa970000000 rw-s 00000000 ca:01 25190272                   /home/zhanghaoxin/FileMmapTest.txt
Size:            2097152 kB
Rss:             2097152 kB
Pss:              493463 kB
Shared_Clean:    2097152 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         0 kB
Referenced:      2014104 kB
Anonymous:             0 kB
AnonHugePages:         0 kB
Swap:                  0 kB
--
7fa970000000-7fa9f0000000 rw-s 00000000 ca:01 25190272                   /home/zhanghaoxin/FileMmapTest.txt
Size:            2097152 kB
Rss:             2097152 kB
Pss:              493463 kB
Shared_Clean:    2097152 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         0 kB
Referenced:      2014104 kB
Anonymous:             0 kB
AnonHugePages:         0 kB
Swap:                  0 kB
--
7fa9f0000000-7faa70000000 rw-s 00000000 ca:01 25190272                   /home/zhanghaoxin/FileMmapTest.txt
Size:            2097152 kB
Rss:             2097152 kB
Pss:              493463 kB
Shared_Clean:    2097152 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         0 kB
Referenced:      2014104 kB
Anonymous:             0 kB
AnonHugePages:         0 kB
Swap:                  0 kB
--
7faa70000000-7faaf0000000 rw-s 00000000 ca:01 25190272                   /home/zhanghaoxin/FileMmapTest.txt
Size:            2097152 kB
Rss:              616496 kB
Pss:              123299 kB
Shared_Clean:     616496 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         0 kB
Referenced:       616492 kB
Anonymous:             0 kB
AnonHugePages:         0 kB
Swap:                  0 kB

其中比較重要的8個字段的含義分別以下:app

  • Size:表示該映射區域在虛擬內存空間中的大小。
  • Rss:表示該映射區域當前在物理內存中佔用了多少空間 
  • Pss:該虛擬內存區域平攤計算後使用的物理內存大小(有些內存會和其餘進程共享,例如mmap進來的)。好比該區域所映射的物理內存部分同時也被另外一個進程映射了,且該部分物理內存的大小爲1000KB,那麼該進程分攤其中一半的內存,即Pss=500KB。
  • Shared_Clean:和其餘進程共享的未被改寫的page的大小
  • Shared_Dirty: 和其餘進程共享的被改寫的page的大小
  • Private_Clean:未被改寫的私有頁面的大小。
  • Private_Dirty: 已被改寫的私有頁面的大小。
  • Swap:表示非mmap內存(也叫anonymous memory,好比malloc動態分配出來的內存)因爲物理內存不足被swap到交換空間的大小。

咱們能夠看到,把這五個MappedByteBuffer的Pss加起來正好是2097151,就是咱們映射的大小。能夠推斷出,咱們這五個MappedByteBuffer在linux中的實現就是對應同一塊內存。
同時,top命令看到的內存並不許,top,命令統計的是RSS字段,其實對於MMAP來講,更準確的應該是統計PSS字段dom

微信搜索「個人編程喵」關注公衆號,每日一刷,輕鬆提高技術,斬獲各類offeride

image

相關文章
相關標籤/搜索