Skip to content

Commit

Permalink
ksm: check and skip page, if it is already scanned
Browse files Browse the repository at this point in the history
On system like Android where most of the process are forked
from parent w/o execve, KSM can scan same page multiple times
in one scan cycle. There is no advantage in scanning same page
multiple times for merging. During testing with Android, it was
observed around 60% pages are skipped for each scan cycle.

Change-Id: I0cf01802f0b4d61fcab92558beb9e1c660dc9a77
Link: http://lkml.kernel.org/r/CAMrOTPgBtANS_ryRjan0-dTL97U7eRvtf3dCsss=Kn+Uk89fuA@mail.gmail.com
Signed-off-by: Pradeep Sawlani <sawlani@amazon.com>

Signed-off-by: Paul Reioux <reioux@gmail.com>
  • Loading branch information
Pradeep Sawlani authored and didhiy committed Mar 28, 2014
1 parent 9efe214 commit b262881
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 0 deletions.
12 changes: 12 additions & 0 deletions include/linux/page-flags.h
Expand Up @@ -114,8 +114,16 @@ enum pageflags {
PG_compound_lock,
#endif
PG_readahead, /* page in a readahead window */
#ifdef CONFIG_KSM_CHECK_PAGE
PG_ksm_scan0, /* page has been scanned by even KSM cycle */
#endif
__NR_PAGEFLAGS,

#ifdef CONFIG_KSM_CHECK_PAGE
/* page has been scanned by odd KSM cycle */
PG_ksm_scan1 = PG_owner_priv_1,
#endif

/* Filesystems */
PG_checked = PG_owner_priv_1,

Expand Down Expand Up @@ -215,6 +223,10 @@ PAGEFLAG(Reserved, reserved) __CLEARPAGEFLAG(Reserved, reserved)
PAGEFLAG(SwapBacked, swapbacked) __CLEARPAGEFLAG(SwapBacked, swapbacked)

__PAGEFLAG(SlobFree, slob_free)
#ifdef CONFIG_KSM_CHECK_PAGE
CLEARPAGEFLAG(KsmScan0, ksm_scan0) TESTSETFLAG(KsmScan0, ksm_scan0)
CLEARPAGEFLAG(KsmScan1, ksm_scan1) TESTSETFLAG(KsmScan1, ksm_scan1)
#endif

#ifdef CONFIG_CLEANCACHE
PAGEFLAG(WasActive, was_active)
Expand Down
10 changes: 10 additions & 0 deletions mm/Kconfig
Expand Up @@ -237,6 +237,16 @@ config KSM
until a program has madvised that an area is MADV_MERGEABLE, and
root has set /sys/kernel/mm/ksm/run to 1 (if CONFIG_SYSFS is set).

config KSM_CHECK_PAGE
bool "Check page before scanning"
depends on KSM
default n
help
If enabled, this will check and skip if page is already scanned in
same KSM scan cycle.
This is useful in situation where you have parent and
child process marking same area for KSM scanning.

config DEFAULT_MMAP_MIN_ADDR
int "Low address space to protect from user allocation"
depends on MMU
Expand Down
28 changes: 28 additions & 0 deletions mm/ksm.c
Expand Up @@ -651,7 +651,9 @@ static void remove_rmap_item_from_tree(struct rmap_item *rmap_item)
* than left over from before.
*/
age = (unsigned char)(ksm_scan.seqnr - rmap_item->address);
#ifndef CONFIG_KSM_CHECK_PAGE
BUG_ON(age > 1);
#endif
if (!age)
rb_erase(&rmap_item->node,
root_unstable_tree + NUMA(rmap_item->nid));
Expand Down Expand Up @@ -1688,6 +1690,31 @@ static struct rmap_item *scan_get_next_rmap_item(struct page **page)
return NULL;
}

static inline int is_page_scanned(struct page *page)
{
#ifdef CONFIG_KSM_CHECK_PAGE
/* page is already marked as ksm, so this will be simple merge */
if (PageKsm(page))
return 0;

if (ksm_scan.seqnr & 0x1) {
/* odd cycle */
/* clear even cycle bit */
ClearPageKsmScan0(page);
/* get old value and mark it scanned */
return TestSetPageKsmScan1(page);
} else {
/* even cycle */
/* clear odd cycle bit */
ClearPageKsmScan1(page);
/* get old value and mark it scanned */
return TestSetPageKsmScan0(page);
}
#else
return 0;
#endif
}

/**
* ksm_do_scan - the ksm scanner main worker function.
* @scan_npages - number of pages we want to scan before we return.
Expand All @@ -1702,6 +1729,7 @@ static void ksm_do_scan(unsigned int scan_npages)
rmap_item = scan_get_next_rmap_item(&page);
if (!rmap_item)
return;
if (!is_page_scanned(page))
cmp_and_merge_page(page, rmap_item);
put_page(page);
}
Expand Down

0 comments on commit b262881

Please sign in to comment.