RFR: 8234930: Use MAP_JIT when allocating pages for code cache on macOS [v6]

Anton Kozlov akozlov at openjdk.java.net
Sat Dec 5 10:56:13 UTC 2020


On Sat, 5 Dec 2020 05:34:57 GMT, Thomas Stuefe <stuefe at openjdk.org> wrote:

> I found this: https://stackoverflow.com/questions/7718964/how-can-i-force-macos-to-release-madv-freed-pages. One remark recommends MADV_FREE_REUSABLE to deal with the display problem; could that be a solution 

I'd found MADV_FREE_REUSABLE as well. One problem is that it's barely documented. The only description from the vendor I could find was
#define MADV_FREE               5       /* pages unneeded, discard contents */
#define MADV_ZERO_WIRED_PAGES   6       /* zero the wired pages that have not been unwired before the entry is deleted */
#define MADV_FREE_REUSABLE      7       /* pages can be reused (by anyone) */
#define MADV_FREE_REUSE         8       /* caller wants to reuse those pages */

The other problem, it cannot substitute mmap completely, see below.

> My only remaining question is: is there really an observable difference between replacing the mapping with mmap and calling madvice(MADV_FREE)? And if there is, does it matter in practice?

Yes, it is. For a sample program after uncommit implemented by different ways, mmap the only way to reduce occupied memory size in Activity Monitor (system GUI application user will likely look to).

* no uncommit
./test noop              
do not uncommit          
Physical footprint:         512.3M
Physical footprint (peak):  512.3M
VM_ALLOCATE                 109951000-111951000    [128.0M 128.0M 128.0M     0K] rw-/rwx SM=COW          
VM_ALLOCATE                 111951000-119951000    [128.0M 128.0M 128.0M     0K] rw-/rwx SM=COW          
VM_ALLOCATE                 119951000-121951000    [128.0M 128.0M 128.0M     0K] rw-/rwx SM=COW          
VM_ALLOCATE                 121951000-129951000    [128.0M 128.0M 128.0M     0K] rw-/rwx SM=COW          
                                VIRTUAL RESIDENT    DIRTY  SWAPPED VOLATILE   NONVOL    EMPTY   REGION   
REGION TYPE                        SIZE     SIZE     SIZE     SIZE     SIZE     SIZE     SIZE    COUNT (non-coalesced) 
===========                     ======= ========    =====  ======= ========   ======    =====  =======   
VM_ALLOCATE                      512.0M   512.0M   512.0M       0K       0K       0K       0K        4  

* MADV_FREE reduces Dirty size, but does not affect Rss and Physical footprint
./test madv_free
madvise 
Physical footprint:         512.3M
Physical footprint (peak):  512.3M
VM_ALLOCATE                 108269000-110269000    [128.0M 128.0M     0K     0K] rw-/rwx SM=COW
VM_ALLOCATE                 110269000-118269000    [128.0M 128.0M     0K     0K] rw-/rwx SM=COW
VM_ALLOCATE                 118269000-120269000    [128.0M 128.0M     0K     0K] rw-/rwx SM=COW  
VM_ALLOCATE                 120269000-128269000    [128.0M 128.0M     0K     0K] rw-/rwx SM=COW  
                                VIRTUAL RESIDENT    DIRTY  SWAPPED VOLATILE   NONVOL    EMPTY   REGION
REGION TYPE                        SIZE     SIZE     SIZE     SIZE     SIZE     SIZE     SIZE    COUNT (non-coalesced)
===========                     ======= ========    =====  ======= ========   ======    =====  =======
VM_ALLOCATE                      512.0M   512.0M       0K       0K       0K       0K       0K        4
* MADV_FREE_REUSABLE reduces Physical footprint (whatever it is)
./test madv_free_reuse          
madvise reuse                    
Physical footprint:         292K
Physical footprint (peak):  512.3M
VM_ALLOCATE                 10d568000-115568000    [128.0M 128.0M     0K     0K] rw-/rwx SM=COW
VM_ALLOCATE                 115568000-11d568000    [128.0M 128.0M     0K     0K] rw-/rwx SM=COW
VM_ALLOCATE                 11d568000-125568000    [128.0M 128.0M     0K     0K] rw-/rwx SM=COW
VM_ALLOCATE                 125568000-12d568000    [128.0M 128.0M     0K     0K] rw-/rwx SM=COW
                                VIRTUAL RESIDENT    DIRTY  SWAPPED VOLATILE   NONVOL    EMPTY   REGION
REGION TYPE                        SIZE     SIZE     SIZE     SIZE     SIZE     SIZE     SIZE    COUNT (non-coalesced)
===========                     ======= ========    =====  ======= ========   ======    =====  =======
VM_ALLOCATE                      512.0M   512.0M       0K       0K       0K       0K       0K        4
There is a problem that Activity Monitor apparently looks for Rss and reports no change:

![2020-12-05-130210_956x42_scrot](https://user-images.githubusercontent.com/919084/101240204-d51d6a80-36fe-11eb-806b-30c06ad90a81.png)

* and mmap reduces Rss as well
./test mmap              
new mmap                 
Physical footprint:         292K
Physical footprint (peak):  512.3M
VM_ALLOCATE                 10df01000-12df01000    [512.0M     0K     0K     0K] ---/rwx SM=NUL          
                                VIRTUAL RESIDENT    DIRTY  SWAPPED VOLATILE   NONVOL    EMPTY   REGION   
REGION TYPE                        SIZE     SIZE     SIZE     SIZE     SIZE     SIZE     SIZE    COUNT (non-coalesced) 
===========                     ======= ========    =====  ======= ========   ======    =====  =======   
VM_ALLOCATE                      512.0M       0K       0K       0K       0K       0K       0K      

Activity Monitor (results are OK now)

![2020-12-05-131429_973x36_scrot](https://user-images.githubusercontent.com/919084/101240215-ea929480-36fe-11eb-858a-cef8a0f3327e.png)

So, when possible, we should do new mmap for uncommit.

---
Source code for the test:
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/mman.h>

int main(int argc, char *argv[]) {
        char r;

        int pagesize = 4096;
        int size = 512 * 1024 * 1024;

        char *a = mmap(NULL, size,
                        PROT_NONE,
                        MAP_ANON | MAP_PRIVATE, -1, 0);
        if (a == MAP_FAILED) {
                perror("mmap()");
                return 1;
        }

        if (mprotect(a, size, PROT_READ | PROT_WRITE)) {
                perror("mprotect");
                return 1;
        }

        for (int i = 0; i < size; i += 4096) {
                a[i] = 1;
        }

        if (!strcmp(argv[1], "madv_free")) {
                printf("madvise\n");
                if (mprotect(a, PROT_NONE, size)) {
                        perror("mprotect");
                        return 1;
                }
                if (madvise(a, size, MADV_FREE)) {
                        perror("madvise");
                        return 1;
                }
        } else if (!strcmp(argv[1], "madv_free_reuse")) {
                printf("madvise reuse\n");
                if (mprotect(a, PROT_NONE, size)) {
                        perror("mprotect");
                        return 1;
                }
                if (madvise(a, size, MADV_FREE_REUSABLE)) {
                        perror("madvise");
                        return 1;
                }
        } else if (!strcmp(argv[1], "mmap")) {
                printf("new mmap\n");
                if (MAP_FAILED == mmap(a, size, PROT_NONE, MAP_ANON | MAP_PRIVATE| MAP_FIXED, -1, 0)) {
                        perror("mmap2");
                        return 1;
                }
        } else {
                printf("do not uncommit\n");
        }
        fflush(stdout);

        char cmd[128];
        snprintf(cmd, sizeof(cmd), "vmmap %d | awk '/Phys/ || /VM_ALLOCATE/'", getpid());
        system(cmd);

        read(0, &r, 1);

        return 0;
}

-------------

PR: https://git.openjdk.java.net/jdk/pull/294


More information about the hotspot-dev mailing list