mm swapping improvements
Subsystems (8)
PATCH 1/1 mm swapping improvements
Hi list,
Attached is a patchset against 2.6.2-rc2-mm1 which includes two of Nikita's patches and one of my own, and backs out the RSS limit patch due to some problems (discussion of these patches on linux-mm). The patchset improves VM performance under swapping quite significantly for kbuild - its now close 2.4 or better in some cases.
I haven't done many other tests so I would like anyone who's had swapping related slowdowns when moving from 2.4 to 2.6, and is interested in helping improve it to test out the patch please. I can make a patch against the -linus kernel if anyone would like.
Some benchmarks: http://www.kerneltrap.org/~npiggin/vm/3/
Green is 2.6, red is 2.4, purple is 2.6 with this patch.
Thank you.
Nick
PS (the usual disclaimer about mm patches vs your data)
linux-2.6-npiggin/include/linux/init_task.h | 2 linux-2.6-npiggin/include/linux/mmzone.h | 6 + linux-2.6-npiggin/include/linux/sched.h | 1 linux-2.6-npiggin/include/linux/swap.h | 4 linux-2.6-npiggin/kernel/sys.c | 8 - linux-2.6-npiggin/mm/page_alloc.c | 20 +++ linux-2.6-npiggin/mm/rmap.c | 19 --- linux-2.6-npiggin/mm/vmscan.c | 162 +++++++++++++++++----------- 8 files changed, 130 insertions(+), 92 deletions(-)
include/linux/init_task.h renamed from include/linux/init_task.h~rollup +0 -2
@@ -2,7 +2,6 @@#define _LINUX__INIT_TASK_H#include <linux/file.h> -#include <asm/resource.h> #define INIT_FILES \ { \
@@ -43,7 +42,6 @@ .mmlist = LIST_HEAD_INIT(name.mmlist), \ .cpu_vm_mask = CPU_MASK_ALL, \ .default_kioctx = INIT_KIOCTX(name.default_kioctx, name), \ - .rlimit_rss = RLIM_INFINITY \ }#define INIT_SIGNALS (sig) { \
include/linux/mmzone.h renamed from include/linux/mmzone.h~rollup +6 -0
@@ -149,6 +149,12 @@ struct zone {unsigned long zone_start_pfn;/* +* dummy page used as place holder during scanning of +* active_list in refill_inactive_zone() +*/ +struct page *scan_page; + +/* * rarely used fields: */ char *name;
include/linux/sched.h renamed from include/linux/sched.h~rollup +0 -1
@@ -206,7 +206,6 @@ struct mm_struct {unsigned long arg_start, arg_end, env_start, env_end;unsigned long rss, total_vm, locked_vm;unsigned long def_flags; -unsigned long rlimit_rss;cpumask_t cpu_vm_mask;unsigned long saved_auxv[40 ];/* for /proc/PID/auxv */
include/linux/swap.h renamed from include/linux/swap.h~rollup +2 -2
@@ -179,7 +179,7 @@ extern int vm_swappiness;/* linux/mm/rmap.c */ #ifdef CONFIG_MMU -int FASTCALL (page_referenced (struct page *,int *)); +int FASTCALL (page_referenced (struct page *));struct pte_chain *FASTCALL (page_add_rmap (struct page *,pte_t *,struct pte_chain *));void FASTCALL (page_remove_rmap (struct page *,pte_t *));
@@ -188,7 +188,7 @@ int FASTCALL(try_to_unmap(struct page *)/* linux/mm/shmem.c */ extern int shmem_unuse (swp_entry_t entry,struct page *page);#else -#define page_referenced (page, _x) TestClearPageReferenced(page) +#define page_referenced (page) TestClearPageReferenced(page)#define try_to_unmap (page) SWAP_FAIL#endif /* CONFIG_MMU */
kernel/sys.c renamed from kernel/sys.c~rollup +0 -8
@@ -1306,14 +1306,6 @@ asmlinkage long sys_setrlimit(unsigned iif (retval)return retval; -/* The rlimit is specified in bytes, convert to pages for mm. */ -if (resource ==RLIMIT_RSS && current->mm) { -unsigned long pages =RLIM_INFINITY ; -if (new_rlim.rlim_cur !=RLIM_INFINITY ) - pages = new_rlim.rlim_cur >>PAGE_SHIFT ; - current->mm->rlimit_rss = pages; - } - *old_rlim = new_rlim;return 0 ; }
mm/page_alloc.c renamed from mm/page_alloc.c~rollup +20 -0
@@ -1211,6 +1211,9 @@ void __init memmap_init_zone(struct page memmap_init_zone((start), (size), (nid), (zone), (start_pfn))#endif +/* dummy pages used to scan active lists */ +static struct page scan_pages[MAX_NUMNODES ][MAX_NR_ZONES ]; +/* * Set up the zone data structures: * - mark all pages reserved
@@ -1233,6 +1236,7 @@ static void __init free_area_init_core(sstruct zone *zone = pgdat->node_zones + j;unsigned long size, realsize;unsigned long batch; +struct page *scan_page; zone_table[NODEZONE (nid, j)] = zone; realsize = size = zones_size[j];
@@ -1287,6 +1291,22 @@ static void __init free_area_init_core(satomic_set (&zone->refill_counter,0 ); zone->nr_active =0 ; zone->nr_inactive =0 ; + +/* initialize dummy page used for scanning */ + scan_page = &scan_pages[nid][j]; + zone->scan_page = scan_page; +memset (scan_page,0 ,sizeof *scan_page); + scan_page->flags = + (1 << PG_locked) | + (1 << PG_error) | + (1 << PG_lru) | + (1 << PG_active) | + (1 << PG_reserved); +set_page_zone (scan_page, j); +page_cache_get (scan_page); +INIT_LIST_HEAD (&scan_page->list); +list_add (&scan_page->lru, &zone->active_list); +if (!size)continue ;
mm/rmap.c renamed from mm/rmap.c~rollup +1 -18
@@ -104,8 +104,6 @@ pte_chain_encode(struct pte_chain *pte_c/** * page_referenced - test if the page was referenced * @page: the page to test -* @rsslimit: set if the process(es) using the page is(are) over RSS limit. -* Cleared otherwise. * * Quick test_and_clear_referenced for all mappings to a page, * returns the number of processes which referenced the page.
@@ -113,13 +111,9 @@ pte_chain_encode(struct pte_chain *pte_c* * If the page has a single-entry pte_chain, collapse that back to a PageDirect * representation. This way, it's only done under memory pressure. -* -* The pte_chain_lock() is sufficient to pin down mm_structs which we examine -* them. */ -int page_referenced (struct page *page,int *rsslimit) +int page_referenced (struct page * page) { -struct mm_struct * mm;struct pte_chain *pc;int referenced =0 ;
@@ -133,17 +127,10 @@ int page_referenced(struct page *page, ipte_t *pte =rmap_ptep_map (page->pte.direct);if (ptep_test_and_clear_young (pte)) referenced++; - - mm =ptep_to_mm (pte); -if (mm->rss > mm->rlimit_rss) - *rsslimit =1 ;rmap_ptep_unmap (pte); }else {int nr_chains =0 ; -/* We clear it if any task using the page is under its limit. */ - *rsslimit =1 ; -/* Check all the page tables mapping this page. */ for (pc = page->pte.chain; pc; pc =pte_chain_next (pc)) {int i;
@@ -155,10 +142,6 @@ int page_referenced(struct page *page, i p =rmap_ptep_map (pte_paddr);if (ptep_test_and_clear_young (p)) referenced++; - - mm =ptep_to_mm (p); -if (mm->rss < mm->rlimit_rss) - *rsslimit =0 ;rmap_ptep_unmap (p); nr_chains++; }
mm/vmscan.c renamed from mm/vmscan.c~rollup +101 -61
256 lines not on this page · raw message
_
Quoted 8 lines · Nick Piggin
Hi list,
Attached is a patchset against 2.6.2-rc2-mm1 which includes two of Nikita's patches and one of my own, and backs out the RSS limit patch due to some problems (discussion of these patches on linux-mm). The patchset improves VM performance under swapping quite significantly for kbuild - its now close 2.4 or better in some cases.
Quoted 8 lines
I haven't done many other tests so I would like anyone who's had swapping related slowdowns when moving from 2.4 to 2.6, and is interested in helping improve it to test out the patch please. I can make a patch against the -linus kernel if anyone would like.
Some benchmarks: http://www.kerneltrap.org/~npiggin/vm/3/
Green is 2.6, red is 2.4, purple is 2.6 with this patch.
OK here is the patch for 2.6.2-rc2. Only compile tested but there isn't much difference between -linus and -mm in this area so it should be fine.
linux-2.6-npiggin/include/linux/mmzone.h | 6 + linux-2.6-npiggin/mm/page_alloc.c | 20 ++++ linux-2.6-npiggin/mm/vmscan.c | 152 +++++++++++++++++++------------ 3 files changed, 124 insertions(+), 54 deletions(-)
include/linux/mmzone.h renamed from include/linux/mmzone.h~rollup +6 -0
@@ -149,6 +149,12 @@ struct zone {unsigned long zone_start_pfn;/* +* dummy page used as place holder during scanning of +* active_list in refill_inactive_zone() +*/ +struct page *scan_page; + +/* * rarely used fields: */ char *name;
mm/page_alloc.c renamed from mm/page_alloc.c~rollup +20 -0
@@ -1230,6 +1230,9 @@ void __init memmap_init_zone(struct page memmap_init_zone((start), (size), (nid), (zone), (start_pfn))#endif +/* dummy pages used to scan active lists */ +static struct page scan_pages[MAX_NUMNODES ][MAX_NR_ZONES ]; +/* * Set up the zone data structures: * - mark all pages reserved
@@ -1252,6 +1255,7 @@ static void __init free_area_init_core(sstruct zone *zone = pgdat->node_zones + j;unsigned long size, realsize;unsigned long batch; +struct page *scan_page; zone_table[NODEZONE (nid, j)] = zone; realsize = size = zones_size[j];
@@ -1306,6 +1310,22 @@ static void __init free_area_init_core(satomic_set (&zone->refill_counter,0 ); zone->nr_active =0 ; zone->nr_inactive =0 ; + +/* initialize dummy page used for scanning */ + scan_page = &scan_pages[nid][j]; + zone->scan_page = scan_page; +memset (scan_page,0 ,sizeof *scan_page); + scan_page->flags = + (1 << PG_locked) | + (1 << PG_error) | + (1 << PG_lru) | + (1 << PG_active) | + (1 << PG_reserved); +set_page_zone (scan_page, j); +page_cache_get (scan_page); +INIT_LIST_HEAD (&scan_page->list); +list_add (&scan_page->lru, &zone->active_list); +if (!size)continue ;
mm/vmscan.c renamed from mm/vmscan.c~rollup +98 -54
235 lines not on this page · raw message
_