thp, vmstats: count deferred split events
authorKirill A. Shutemov <kirill.shutemov@linux.intel.com>
Thu, 17 Mar 2016 21:18:45 +0000 (14:18 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 17 Mar 2016 22:09:34 +0000 (15:09 -0700)
Count how many times we put a THP in split queue.  Currently, it happens
on partial unmap of a THP.

Rapidly growing value can indicate that an application behaves
unfriendly wrt THP: often fault in huge page and then unmap part of it.
This leads to unnecessary memory fragmentation and the application may
require tuning.

The event also can help with debugging kernel [mis-]behaviour.

Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Documentation/vm/transhuge.txt
include/linux/vm_event_item.h
mm/huge_memory.c
mm/vmstat.c

index 21cf34f3ddb268c5a64478db776d05333027cc54..0dc8632aa01e731d05e6c990e4c22461b499e7ca 100644 (file)
@@ -229,6 +229,11 @@ thp_split_page is incremented every time a huge page is split into base
 thp_split_page_failed is is incremented if kernel fails to split huge
        page. This can happen if the page was pinned by somebody.
 
+thp_deferred_split_page is incremented when a huge page is put onto split
+       queue. This happens when a huge page is partially unmapped and
+       splitting it would free up some memory. Pages on split queue are
+       going to be split under memory pressure.
+
 thp_split_pmd is incremented every time a PMD split into table of PTEs.
        This can happen, for instance, when application calls mprotect() or
        munmap() on part of huge page. It doesn't split huge page, only
index 58ecc056ee45703ad4bba32a22fb106edfd3adfc..ec084321fe092cac05d0c8c003c8448a4188c795 100644 (file)
@@ -72,6 +72,7 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
                THP_COLLAPSE_ALLOC_FAILED,
                THP_SPLIT_PAGE,
                THP_SPLIT_PAGE_FAILED,
+               THP_DEFERRED_SPLIT_PAGE,
                THP_SPLIT_PMD,
                THP_ZERO_PAGE_ALLOC,
                THP_ZERO_PAGE_ALLOC_FAILED,
index 1ea21e203a700114587dedca262f9267bb5a005a..1dddfb21fc2244d452edb7e2b514fe1ade1b368f 100644 (file)
@@ -3455,6 +3455,7 @@ void deferred_split_huge_page(struct page *page)
 
        spin_lock_irqsave(&pgdata->split_queue_lock, flags);
        if (list_empty(page_deferred_list(page))) {
+               count_vm_event(THP_DEFERRED_SPLIT_PAGE);
                list_add_tail(page_deferred_list(page), &pgdata->split_queue);
                pgdata->split_queue_len++;
        }
index f80066248c948df5d7de42d0246a419ed249df5e..5e43004828971e778a185ec69f2ef9710f085fb4 100644 (file)
@@ -848,6 +848,7 @@ const char * const vmstat_text[] = {
        "thp_collapse_alloc_failed",
        "thp_split_page",
        "thp_split_page_failed",
+       "thp_deferred_split_page",
        "thp_split_pmd",
        "thp_zero_page_alloc",
        "thp_zero_page_alloc_failed",