Skip to contentSkip to conversation

New: transparent hugepage not compatable with madvise(MADV_DONTNEED)

Bug 202089 Andrew Morton 4 participants 6 messages Dec 29, 2018 – Jan 3, 2019 1 message not in the archive Memory management

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]/

Andrew Morton

author maintainer
#1 lore raw

(switched to email. Please respond via emailed reply-to-all, not via the bugzilla web interface).

Quoted 83 lines · On Sat, 29 Dec 2018 09:00:22 +0000 [email protected] wrote:

https://bugzilla.kernel.org/show_bug.cgi?id=202089

            Bug ID: 202089
           Summary: transparent hugepage not compatable with
                    madvise(MADV_DONTNEED)
           Product: Memory Management
           Version: 2.5
    Kernel Version: 4.4.0-117
          Hardware: x86-64
                OS: Linux
              Tree: Mainline
            Status: NEW
          Severity: high
          Priority: P1
         Component: Other
          Assignee: [email protected]
          Reporter: [email protected]
        Regression: No

environment:
1.kernel 4.4.0 on x86_64
2.echo always > /sys/kernel/mm/transparent_hugepage/enable
echo always > /sys/kernel/mm/transparent_hugepage/defrag
echo 2000000 > /sys/kernel/mm/transparent_hugepage/khugepaged/pages_to_scan
( faster defrag pages to reproduce problem)

problem:
1. use mmap() to allocate 4096 bytes for 1024*512 times (4096*1024*512=2G).
2. use madvise(MADV_DONTNEED) to free most of the above pages, but reserve a
few pages(by if(i%33==0) continue;), then process's physical memory firstly come down, but after a few seconds, it rise back to 2G again, and can't come down forever.
3. if i delete this condition(if(i%33==0) continue;) or disable
transparent_hugepage by setting 'enable' and 'defrag' to never, all go well and the physical memory can come down expectly.

It seems like transparent_hugepage has problems with non-contiguous
madvise(MADV_DONTEED).

Belows is the test code:

#include <stdio.h>
#include <memory.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <errno.h>
#include <assert.h>

#define PAGE_SIZE 4096
#define PAGE_COUNT 1024*512
int main()
{
void** table = (void**)malloc(sizeof(void*) * PAGE_COUNT); printf("begin mmap...\n");

for (int i=0; i<PAGE_COUNT; i++) {
table[i] = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,

MAP_PRIVATE|MAP_ANONYMOUS, -1 ,0);
    assert(table[i] != MAP_FAILED);
    memset(table[i], 1, PAGE_SIZE);

}

printf("mmap ok, press enter to free most of them\n"); getchar();

//it behaves not expectly: after most pages freed, thp make it rise to 2G
again

  for(int i=0; i<PAGE_COUNT; i++) {
    if (i%33==0) continue;
    if (madvise(table[i], PAGE_SIZE, MADV_DONTNEED) != 0)
      printf("madvise error, errno:%d\n", errno);

}

printf("munmap finish\n");
free(table);
getchar();
getchar();
}

Signature · 2 lines
You are receiving this mail because:
You are the assignee for the bug.
#2 lore raw
Quoted 44 lines · Andrew Morton

(switched to email. Please respond via emailed reply-to-all, not via the bugzilla web interface).

Quoted 38 lines · On Sat, 29 Dec 2018 09:00:22 +0000 [email protected] wrote:

https://bugzilla.kernel.org/show_bug.cgi?id=202089

            Bug ID: 202089
           Summary: transparent hugepage not compatable with
                    madvise(MADV_DONTNEED)
           Product: Memory Management
           Version: 2.5
    Kernel Version: 4.4.0-117
          Hardware: x86-64
                OS: Linux
              Tree: Mainline
            Status: NEW
          Severity: high
          Priority: P1
         Component: Other
          Assignee: [email protected]
          Reporter: [email protected]
        Regression: No

environment:
1.kernel 4.4.0 on x86_64
2.echo always > /sys/kernel/mm/transparent_hugepage/enable
echo always > /sys/kernel/mm/transparent_hugepage/defrag
echo 2000000 > /sys/kernel/mm/transparent_hugepage/khugepaged/pages_to_scan
( faster defrag pages to reproduce problem)

problem:
1. use mmap() to allocate 4096 bytes for 1024*512 times (4096*1024*512=2G).
2. use madvise(MADV_DONTNEED) to free most of the above pages, but reserve a
few pages(by if(i%33==0) continue;), then process's physical memory firstly come down, but after a few seconds, it rise back to 2G again, and can't come down forever.
3. if i delete this condition(if(i%33==0) continue;) or disable
transparent_hugepage by setting 'enable' and 'defrag' to never, all go well and the physical memory can come down expectly.

It seems like transparent_hugepage has problems with non-contiguous
madvise(MADV_DONTEED).

It's expected behaviour.

MADV_DONTNEED doesn't guarantee that the range will not be repopulated (with or without direct action on application behalf). It's just a hint for the kernel.

For sparse mappings, consider using MADV_NOHUGEPAGE.

Signature · 1 line
 Kirill A. Shutemov
#3 lore raw
Quoted 43 lines · Kirill A. Shutemov
Quoted 42 lines · Andrew Morton

(switched to email. Please respond via emailed reply-to-all, not via the bugzilla web interface).

Quoted 36 lines · On Sat, 29 Dec 2018 09:00:22 +0000 [email protected] wrote:

https://bugzilla.kernel.org/show_bug.cgi?id=202089

            Bug ID: 202089
           Summary: transparent hugepage not compatable with
                    madvise(MADV_DONTNEED)
           Product: Memory Management
           Version: 2.5
    Kernel Version: 4.4.0-117
          Hardware: x86-64
                OS: Linux
              Tree: Mainline
            Status: NEW
          Severity: high
          Priority: P1
         Component: Other
          Assignee: [email protected]
          Reporter: [email protected]
        Regression: No

environment:
1.kernel 4.4.0 on x86_64
2.echo always > /sys/kernel/mm/transparent_hugepage/enable
echo always > /sys/kernel/mm/transparent_hugepage/defrag
echo 2000000 > /sys/kernel/mm/transparent_hugepage/khugepaged/pages_to_scan
( faster defrag pages to reproduce problem)

problem:
1. use mmap() to allocate 4096 bytes for 1024*512 times (4096*1024*512=2G).
2. use madvise(MADV_DONTNEED) to free most of the above pages, but reserve a
few pages(by if(i%33==0) continue;), then process's physical memory firstly come down, but after a few seconds, it rise back to 2G again, and can't come down forever.
3. if i delete this condition(if(i%33==0) continue;) or disable
transparent_hugepage by setting 'enable' and 'defrag' to never, all go well and the physical memory can come down expectly.

Quoted 8 lines
Quoted 2 lines
Quoted 2 lines

It seems like transparent_hugepage has problems with non-contiguous
madvise(MADV_DONTEED).

It's expected behaviour.

MADV_DONTNEED doesn't guarantee that the range will not be repopulated (with or without direct action on application behalf). It's just a hint for the kernel.

I agree with Kirill here but I would be interested in the underlying usecase that triggered this. The test case is clearly artificial but is any userspace actually relying on MADV_DONTNEED reducing the rss longterm?

Quoted 1 line

For sparse mappings, consider using MADV_NOHUGEPAGE.

Yes or use a high threshold for khugepaged for collapsing.

Signature · 2 lines
Michal Hocko
SUSE Labs
#4 lore raw
Quoted 16 lines · Michal Hocko
Quoted 15 lines · Kirill A. Shutemov
Quoted 11 lines · Andrew Morton
Quoted 11 lines

1. use mmap() to allocate 4096 bytes for 1024*512 times (4096*1024*512=2G).
2. use madvise(MADV_DONTNEED) to free most of the above pages, but reserve a
few pages(by if(i%33==0) continue;), then process's physical memory firstly come down, but after a few seconds, it rise back to 2G again, and can't come down forever.
3. if i delete this condition(if(i%33==0) continue;) or disable
transparent_hugepage by setting 'enable' and 'defrag' to never, all go well and the physical memory can come down expectly.

It seems like transparent_hugepage has problems with non-contiguous
madvise(MADV_DONTEED).

It's expected behaviour.

Quoted 10 lines
Quoted 3 lines

MADV_DONTNEED doesn't guarantee that the range will not be repopulated (with or without direct action on application behalf). It's just a hint for the kernel.

I agree with Kirill here but I would be interested in the underlying usecase that triggered this. The test case is clearly artificial but is any userspace actually relying on MADV_DONTNEED reducing the rss longterm?

Quoted 1 line

For sparse mappings, consider using MADV_NOHUGEPAGE.

Should the MADV_DONTNEED hint imply MADV_NOHUGEPAGE? It'd prevent coalescing elsewhere in the VMA, so that might negatively affect other programs.

#5 lore raw
Quoted 26 lines · Matthew Wilcox
Quoted 25 lines · Michal Hocko
Quoted 10 lines · Kirill A. Shutemov
Quoted 9 lines · Andrew Morton
Quoted 9 lines

1. use mmap() to allocate 4096 bytes for 1024*512 times (4096*1024*512=2G).
2. use madvise(MADV_DONTNEED) to free most of the above pages, but reserve a
few pages(by if(i%33==0) continue;), then process's physical memory firstly come down, but after a few seconds, it rise back to 2G again, and can't come down forever.
3. if i delete this condition(if(i%33==0) continue;) or disable
transparent_hugepage by setting 'enable' and 'defrag' to never, all go well and the physical memory can come down expectly.

Quoted 8 lines
Quoted 2 lines
Quoted 2 lines

It seems like transparent_hugepage has problems with non-contiguous
madvise(MADV_DONTEED).

It's expected behaviour.

MADV_DONTNEED doesn't guarantee that the range will not be repopulated (with or without direct action on application behalf). It's just a hint for the kernel.

I agree with Kirill here but I would be interested in the underlying usecase that triggered this. The test case is clearly artificial but is any userspace actually relying on MADV_DONTNEED reducing the rss longterm?

Quoted 5 lines
Quoted 1 line
Quoted 1 line

For sparse mappings, consider using MADV_NOHUGEPAGE.

Should the MADV_DONTNEED hint imply MADV_NOHUGEPAGE? It'd prevent coalescing elsewhere in the VMA, so that might negatively affect other programs.

I really do not think this is a good idea. MADV_DONTEED doesn't really imply anything to future rss. It only wipes out the current content. In other words do we want to stop fault around/readahead or any other optimistic faulting on MADV_DONTEED?

Signature · 2 lines
Michal Hocko
SUSE Labs
#6 lore raw
In reply to Matthew Wilcox
Quoted 26 lines · Matthew Wilcox
Quoted 25 lines · Michal Hocko
Quoted 10 lines · Kirill A. Shutemov
Quoted 9 lines · Andrew Morton
Quoted 9 lines

1. use mmap() to allocate 4096 bytes for 1024*512 times (4096*1024*512=2G).
2. use madvise(MADV_DONTNEED) to free most of the above pages, but reserve a
few pages(by if(i%33==0) continue;), then process's physical memory firstly come down, but after a few seconds, it rise back to 2G again, and can't come down forever.
3. if i delete this condition(if(i%33==0) continue;) or disable
transparent_hugepage by setting 'enable' and 'defrag' to never, all go well and the physical memory can come down expectly.

Quoted 8 lines
Quoted 2 lines
Quoted 2 lines

It seems like transparent_hugepage has problems with non-contiguous
madvise(MADV_DONTEED).

It's expected behaviour.

MADV_DONTNEED doesn't guarantee that the range will not be repopulated (with or without direct action on application behalf). It's just a hint for the kernel.

I agree with Kirill here but I would be interested in the underlying usecase that triggered this. The test case is clearly artificial but is any userspace actually relying on MADV_DONTNEED reducing the rss longterm?

Quoted 5 lines
Quoted 1 line
Quoted 1 line

For sparse mappings, consider using MADV_NOHUGEPAGE.

Should the MADV_DONTNEED hint imply MADV_NOHUGEPAGE? It'd prevent coalescing elsewhere in the VMA, so that might negatively affect other programs.

MADV_NOHUGEPAGE often creates a new VMA (or two) and it has performance implications. And creating a new VMA would require down_write(mmap_sem) which is no-go for MADV_DONTNEED.

Signature · 1 line
 Kirill A. Shutemov