2.6.4-rc2-mm1: vm-split-active-lists
Subsystems (9)
PATCH 1/1 2.6.4-rc2-mm1: vm-split-active-lists
Here is my updated patches rolled into one.
linux-2.6-npiggin/arch/i386/mm/hugetlbpage.c | 4 linux-2.6-npiggin/arch/ia64/mm/hugetlbpage.c | 4 linux-2.6-npiggin/arch/ppc64/mm/hugetlbpage.c | 4 linux-2.6-npiggin/arch/sparc64/mm/hugetlbpage.c | 4 linux-2.6-npiggin/include/linux/mm_inline.h | 33 +++- linux-2.6-npiggin/include/linux/mmzone.h | 28 --- linux-2.6-npiggin/include/linux/page-flags.h | 50 +++--- linux-2.6-npiggin/include/linux/swap.h | 2 linux-2.6-npiggin/kernel/sysctl.c | 9 - linux-2.6-npiggin/mm/page_alloc.c | 26 +-- linux-2.6-npiggin/mm/swap.c | 35 +++- linux-2.6-npiggin/mm/vmscan.c | 193 ++++++++++-------------- 12 files changed, 197 insertions(+), 195 deletions(-)
arch/i386/mm/hugetlbpage.c renamed from arch/i386/mm/hugetlbpage.c~rollup +2 -2
@@ -411,8 +411,8 @@ static void update_and_free_page(struct htlbzone_pages--;for (j =0 ; j < (HPAGE_SIZE /PAGE_SIZE ); j++) { map->flags &= ~(1 << PG_locked |1 << PG_error |1 << PG_referenced | -1 << PG_dirty |1 << PG_active |1 << PG_reserved | -1 << PG_private |1 << PG_writeback); +1 << PG_dirty |1 << PG_active_mapped |1 << PG_active_unmapped | +1 << PG_reserved |1 << PG_private |1 << PG_writeback);set_page_count (map,0 ); map++; }
arch/ia64/mm/hugetlbpage.c renamed from arch/ia64/mm/hugetlbpage.c~rollup +2 -2
@@ -431,8 +431,8 @@ void update_and_free_page(struct page *p htlbzone_pages--;for (j =0 ; j < (HPAGE_SIZE /PAGE_SIZE ); j++) { map->flags &= ~(1 << PG_locked |1 << PG_error |1 << PG_referenced | -1 << PG_dirty |1 << PG_active |1 << PG_reserved | -1 << PG_private |1 << PG_writeback); +1 << PG_dirty |1 << PG_active_mapped |1 << PG_active_unmapped | +1 << PG_reserved |1 << PG_private |1 << PG_writeback);set_page_count (map,0 ); map++; }
arch/ppc64/mm/hugetlbpage.c renamed from arch/ppc64/mm/hugetlbpage.c~rollup +2 -2
@@ -800,8 +800,8 @@ static void split_and_free_hugepage(stru htlbpage_total--;for (j =0 ; j < (HPAGE_SIZE /PAGE_SIZE ); j++) { map->flags &= ~(1 << PG_locked |1 << PG_error |1 << PG_referenced | -1 << PG_dirty |1 << PG_active |1 << PG_reserved | -1 << PG_private |1 << PG_writeback); +1 << PG_dirty |1 << PG_active_mapped |1 << PG_active_unmapped | +1 << PG_reserved |1 << PG_private |1 << PG_writeback);set_page_count (map,0 ); map++; }
arch/sparc64/mm/hugetlbpage.c renamed from arch/sparc64/mm/hugetlbpage.c~rollup +2 -2
@@ -365,8 +365,8 @@ static void update_and_free_page(struct htlbzone_pages--;for (j =0 ; j < (HPAGE_SIZE /PAGE_SIZE ); j++) { map->flags &= ~(1 << PG_locked |1 << PG_error |1 << PG_referenced | -1 << PG_dirty |1 << PG_active |1 << PG_reserved | -1 << PG_private |1 << PG_writeback); +1 << PG_dirty |1 << PG_active_mapped |1 << PG_active_unmapped | +1 << PG_reserved |1 << PG_private |1 << PG_writeback);set_page_count (map,0 ); map++; }
include/linux/mm_inline.h renamed from include/linux/mm_inline.h~rollup +25 -8
@@ -1,9 +1,16 @@static inline void -add_page_to_active_list (struct zone *zone,struct page *page) +add_page_to_active_mapped_list (struct zone *zone,struct page *page) { -list_add (&page->lru, &zone->active_list); - zone->nr_active++; +list_add (&page->lru, &zone->active_mapped_list); + zone->nr_active_mapped++; +} + +static inline void +add_page_to_active_unmapped_list (struct zone *zone,struct page *page) +{ +list_add (&page->lru, &zone->active_unmapped_list); + zone->nr_active_unmapped++; } static inline void
@@ -14,10 +21,17 @@ add_page_to_inactive_list(struct zone *z }static inline void -del_page_from_active_list (struct zone *zone,struct page *page) +del_page_from_active_mapped_list (struct zone *zone,struct page *page) +{ +list_del (&page->lru); + zone->nr_active_mapped--; +} + +static inline void +del_page_from_active_unmapped_list (struct zone *zone,struct page *page) {list_del (&page->lru); - zone->nr_active--; + zone->nr_active_unmapped--; } static inline void
@@ -31,9 +45,12 @@ static inline void del_page_from_lru(struct zone *zone, struct page *page) { list_del(&page->lru); -if (PageActive (page)) { -ClearPageActive (page); - zone->nr_active--; +if (PageActiveMapped (page)) { +ClearPageActiveMapped (page); + zone->nr_active_mapped--; + }else if (PageActiveUnmapped (page)) { +ClearPageActiveUnmapped (page); + zone->nr_active_unmapped--; }else { zone->nr_inactive--; }
include/linux/mmzone.h renamed from include/linux/mmzone.h~rollup +6 -22
@@ -74,11 +74,14 @@ struct zone {ZONE_PADDING (_pad1_) spinlock_t lru_lock; -struct list_head active_list; +struct list_head active_mapped_list; +struct list_head active_unmapped_list;struct list_head inactive_list; -atomic_t nr_scan_active; +atomic_t nr_scan_active_mapped; +atomic_t nr_scan_active_unmapped;atomic_t nr_scan_inactive; -unsigned long nr_active; +unsigned long nr_active_mapped; +unsigned long nr_active_unmapped;unsigned long nr_inactive;int all_unreclaimable;/* All pages pinned */ unsigned long pages_scanned;/* since last reclaim */
@@ -86,25 +89,6 @@ struct zone {ZONE_PADDING (_pad2_)/* -* prev_priority holds the scanning priority for this zone. It is -* defined as the scanning priority at which we achieved our reclaim -* target at the previous try_to_free_pages() or balance_pgdat() -* invokation. -* -* We use prev_priority as a measure of how much stress page reclaim is -* under - it drives the swappiness decision: whether to unmap mapped -* pages. -* -* temp_priority is used to remember the scanning priority at which -* this zone was successfully refilled to free_pages == pages_high. -* -* Access to both these fields is quite racy even on uniprocessor. But -* it is expected to average out OK. -*/ - int temp_priority; -int prev_priority; - -/* * free areas of different sizes */ struct free_area free_area[MAX_ORDER];
include/linux/page-flags.h renamed from include/linux/page-flags.h~rollup +29 -21
63 lines not on this page · raw message
include/linux/swap.h renamed from include/linux/swap.h~rollup +1 -1
@@ -175,7 +175,7 @@ extern void swap_setup(void);/* linux/mm/vmscan.c */ extern int try_to_free_pages (struct zone **,unsigned int ,unsigned int );extern int shrink_all_memory (int ); -extern int vm_swappiness; +extern int vm_mapped_page_cost;/* linux/mm/rmap.c */ #ifdef CONFIG_MMU
kernel/sysctl.c renamed from kernel/sysctl.c~rollup +5 -4
@@ -621,6 +621,7 @@ static ctl_table kern_table[] = {/* Constants for minimum and maximum testing in vm_table. We use these as one-element integer vectors. */ static int zero; +static int one =1 ;static int one_hundred =100 ;
@@ -697,13 +698,13 @@ static ctl_table vm_table[] = { }, { .ctl_name = VM_SWAPPINESS, - .procname = "swappiness", - .data = &vm_swappiness, - .maxlen = sizeof(vm_swappiness), + .procname = "mapped_page_cost", + .data = &vm_mapped_page_cost, + .maxlen = sizeof(vm_mapped_page_cost), .mode = 0644, .proc_handler = &proc_dointvec_minmax, .strategy = &sysctl_intvec, - .extra1 = &zero, + .extra1 = &one, .extra2 = &one_hundred, }, #ifdef CONFIG_HUGETLB_PAGE
mm/page_alloc.c renamed from mm/page_alloc.c~rollup +15 -11
@@ -81,7 +81,7 @@ static void bad_page(const char *functio page->flags &= ~(1 << PG_private |1 << PG_locked |1 << PG_lru | -1 << PG_active | +1 << PG_active_mapped |1 << PG_dirty |1 << PG_writeback);set_page_count (page,0 );
@@ -217,7 +217,8 @@ static inline void free_pages_check(cons1 << PG_lru |1 << PG_private |1 << PG_locked | -1 << PG_active | +1 << PG_active_mapped | +1 << PG_active_unmapped |1 << PG_reclaim |1 << PG_slab | 1 << PG_writeback )))
@@ -324,7 +325,8 @@ static void prep_new_page(struct page *p1 << PG_private |1 << PG_locked |1 << PG_lru | -1 << PG_active | +1 << PG_active_mapped | +1 << PG_active_unmapped |1 << PG_dirty |1 << PG_reclaim | 1 << PG_writeback )))
@@ -818,7 +820,8 @@ unsigned int nr_used_zone_pages(void)struct zone *zone;for_each_zone (zone) - pages += zone->nr_active + zone->nr_inactive; + pages += zone->nr_active_mapped + zone->nr_active_unmapped + + zone->nr_inactive;return pages; }
@@ -955,7 +958,7 @@ void get_zone_counts(unsigned long *acti *inactive =0 ; *free =0 ;for_each_zone (zone) { - *active += zone->nr_active; + *active += zone->nr_active_mapped + zone->nr_active_unmapped; *inactive += zone->nr_inactive; *free += zone->free_pages; }
@@ -1068,7 +1071,7 @@ void show_free_areas(void)K (zone->pages_min),K (zone->pages_low),K (zone->pages_high), -K (zone->nr_active), +K (zone->nr_active_mapped + zone->nr_active_unmapped),K (zone->nr_inactive),K (zone->present_pages) );
@@ -1408,8 +1411,6 @@ static void __init free_area_init_core(s zone->zone_pgdat = pgdat; zone->free_pages =0 ; - zone->temp_priority = zone->prev_priority =DEF_PRIORITY ; -/* * The per-cpu-pages pools are set to around 1000th of the * size of the zone. But no more than 1/4 of a meg - there's
@@ -1443,11 +1444,14 @@ static void __init free_area_init_core(s }printk (" %s zone: %lu pages, LIFO batch:%lu\n" , zone_names[j], realsize, batch); -INIT_LIST_HEAD (&zone->active_list); +INIT_LIST_HEAD (&zone->active_mapped_list); +INIT_LIST_HEAD (&zone->active_unmapped_list);INIT_LIST_HEAD (&zone->inactive_list); -atomic_set (&zone->nr_scan_active,0 ); +atomic_set (&zone->nr_scan_active_mapped,0 ); +atomic_set (&zone->nr_scan_active_unmapped,0 );atomic_set (&zone->nr_scan_inactive,0 ); - zone->nr_active =0 ; + zone->nr_active_mapped =0 ; + zone->nr_active_unmapped =0 ; zone->nr_inactive =0 ;if (!size)continue ;
mm/swap.c renamed from mm/swap.c~rollup +26 -9
@@ -58,14 +58,18 @@ int rotate_reclaimable_page(struct pagereturn 1 ;if (PageDirty (page))return 1 ; -if (PageActive (page)) +if (PageActiveMapped (page)) +return 1 ; +if (PageActiveUnmapped (page))return 1 ;if (!PageLRU (page))return 1 ; zone =page_zone (page);spin_lock_irqsave (&zone->lru_lock, flags); -if (PageLRU (page) && !PageActive (page)) { +if (PageLRU (page) + && !PageActiveMapped (page) && !PageActiveUnmapped (page)) { +list_del (&page->lru);list_add_tail (&page->lru, &zone->inactive_list);inc_page_state (pgrotated);
@@ -84,10 +88,18 @@ void fastcall activate_page(struct pagestruct zone *zone =page_zone (page);spin_lock_irq (&zone->lru_lock); -if (PageLRU (page) && !PageActive (page)) { +if (PageLRU (page) + && !PageActiveMapped (page) && !PageActiveUnmapped (page)) { +del_page_from_inactive_list (zone, page); -SetPageActive (page); -add_page_to_active_list (zone, page); + +if (page_mapped (page)) { +SetPageActiveMapped (page); +add_page_to_active_mapped_list (zone, page); + }else { +SetPageActiveUnmapped (page); +add_page_to_active_unmapped_list (zone, page); + }inc_page_state (pgactivate); }spin_unlock_irq (&zone->lru_lock);
@@ -102,7 +114,8 @@ void fastcall activate_page(struct page*/ void fastcall mark_page_accessed(struct page *page) { -if (!PageActive (page) &&PageReferenced (page) &&PageLRU (page)) { +if (!PageActiveMapped (page) && !PageActiveUnmapped (page) + &&PageReferenced (page) &&PageLRU (page)) {activate_page (page);ClearPageReferenced (page); }else if (!PageReferenced (page)) {
@@ -310,9 +323,13 @@ void __pagevec_lru_add_active(struct pag }if (TestSetPageLRU (page))BUG (); -if (TestSetPageActive (page)) -BUG (); -add_page_to_active_list (zone, page); +if (page_mapped (page)) { +SetPageActiveMapped (page); +add_page_to_active_mapped_list (zone, page); + }else { +SetPageActiveMapped (page); +add_page_to_active_unmapped_list (zone, page); + } }if (zone)spin_unlock_irq (&zone->lru_lock);
mm/vmscan.c renamed from mm/vmscan.c~rollup +82 -111
372 lines not on this page · raw message
_
On Thursday 11 March 2004 01:04, Nick Piggin wrote:
Hi Nick,
Quoted 1 line
Here is my updated patches rolled into one.
hmm, using this in 2.6.4-rc2-mm1 my machine starts to swap very very soon. Machine has squid, bind, apache running, X 4.3.0, Windowmaker, so nothing special.
Swap grows very easily starting to untar'gunzip a kernel tree. About + 150-200MB goes to swap. Everything is very smooth though, but I just wondered because w/o your patches swap isn't used at all, even after some days of uptime.
ciao, Marc
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 5 lines · Marc-Christian Petersen
On Thursday 11 March 2004 01:04, Nick Piggin wrote:
Hi Nick,
Quoted 8 lines
Quoted 2 lines
Here is my updated patches rolled into one.
hmm, using this in 2.6.4-rc2-mm1 my machine starts to swap very very soon. Machine has squid, bind, apache running, X 4.3.0, Windowmaker, so nothing special.
Swap grows very easily starting to untar'gunzip a kernel tree. About + 150-200MB goes to swap. Everything is very smooth though, but I just wondered because w/o your patches swap isn't used at all, even after some days of uptime.
Hmm... I guess it is still smooth because it is swapping out only inactive pages. If the standard VM isn't being pushed very hard it doesn't scan mapped pages at all which is why it isn't swapping.
I have a preference for allowing it to scan some mapped pages though. I'm not sure if there is any attempt at a drop behind logic. That might help. Add new unmapped pagecache pages to the inactive list or something might help... hmm, actually that's what it does now by the looks.
I guess you don't have a problem though.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 6 lines · Nick Piggin
Hmm... I guess it is still smooth because it is swapping out only
inactive pages. If the standard VM isn't being pushed very hard it doesn't scan mapped pages at all which is why it isn't swapping.I have a preference for allowing it to scan some mapped pages though.
I haven't looked at the code but if, as I assume, it is always scanning mapped pages, although at a reduced rate then the effect will be the same as setting swappiness to 100, except it will take longer.
That effect is to cause the whole world to be swapped out when people return to their machines in the morning. Once they're swapped back in the first thing they do it send bitchy emails to you know who.
Quoted 1 line
From a performance perspective it's the right thing to do, but nobody likes
it.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 6 lines · Andrew Morton
Quoted 4 lines · Nick Piggin
Hmm... I guess it is still smooth because it is swapping out only inactive pages. If the standard VM isn't being pushed very hard it doesn't scan mapped pages at all which is why it isn't swapping.
Quoted 8 lines
Quoted 2 lines
I have a preference for allowing it to scan some mapped pages though.
I haven't looked at the code but if, as I assume, it is always scanning mapped pages, although at a reduced rate then the effect will be the same as setting swappiness to 100, except it will take longer.
Yep
Quoted 8 lines
That effect is to cause the whole world to be swapped out when people return to their machines in the morning. Once they're swapped back in the first thing they do it send bitchy emails to you know who.
Quoted 1 line
From a performance perspective it's the right thing to do, but nobody likes
it.
Yeah. I wonder if there is a way to be smarter about dropping these used once pages without putting pressure on more permanent pages... I guess all heuristics will fall down somewhere or other.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 2 lines · Andrew Morton
That effect is to cause the whole world to be swapped out when people return to their machines in the morning.
The correct solution to this problem is "suspend-to-disk" -- if the machine isn't doing anything anyway, TURN IT OFF.
One slightly more practical solution from the "you-now-who gets angry mails" POV anyway, would be to tie the reduced-rate scanning to the load average -- if nothing at all happens, swap-out doesn't need to happen either.
Signature · 1 line
Matthias Urlichs
Quoted 5 lines · Matthias Urlichs
Quoted 2 lines
That effect is to cause the whole world to be swapped out when people return to their machines in the morning.
The correct solution to this problem is "suspend-to-disk" -- if the machine isn't doing anything anyway, TURN IT OFF.
How is that better for people complaining that everything needs to be swapped in in the morning?
Suspend-to-disk will cause everything to be paged in too. Faster I suspect (haven't tried it; it doesn't work on my box), but still a wait especially when you add in the BIOS boot time.
Environmentally turning an unused machine off is good. But I don't see how suspend-to-disk will convince people who are annoyed by swapping in the morning.
Quoted 4 lines
One slightly more practical solution from the "you-now-who gets angry mails" POV anyway, would be to tie the reduced-rate scanning to the load average -- if nothing at all happens, swap-out doesn't need to happen either.
If nothing at all happens, does it matter that pages are written to swap? They're still in RAM as well.
-- Jamie
Quoted 11 lines · Matthias Urlichs
Quoted 3 lines · Andrew Morton
That effect is to cause the whole world to be swapped out when people return to their machines in the morning.
The correct solution to this problem is "suspend-to-disk" -- if the machine isn't doing anything anyway, TURN IT OFF.
Without arguing that point, the VM also should have a solution to the problem where people don't turn it off.
Quoted 6 lines
One slightly more practical solution from the "you-now-who gets angry mails" POV anyway, would be to tie the reduced-rate scanning to the load average -- if nothing at all happens, swap-out doesn't need to happen either.
Well if nothing at all happens we don't swap out, but when something is happening, desktop users don't want any of their programs to be swapped out no matter how long they have been sitting idle. They don't want to wait 10 seconds to page something in even if it means they're waiting an extra 10 minutes throughout the day for their kernel greps and diffs to finish.
Quoted 9 lines · Nick Piggin
Well if nothing at all happens we don't swap out, but when something is happening, desktop users don't want any of their programs to be swapped out no matter how long they have been sitting idle. They don't want to wait 10 seconds to page something in even if it means they're waiting an extra 10 minutes throughout the day for their kernel greps and diffs to finish.
Just had a try of doing things like updatedb and dd if=/dev/zero of=./blah It is pretty swappy I guess. The following patch I think makes things less swappy. It still isn't true dropbehind because new unmapped pages still do place some pressure on the more established pagecache, but not as much.
It is unclear whether full dropbehind is actually good or not. If you have 512MB of memory and a 256MB working set of file data (unmapped), with 400MB of mapped memory doing nothing, after enough thrashing through your 256MB, you'd expect some of that mapped memory to be swapped out.
By the way, I would be interested to know the rationale behind mark_page_accessed as it is without this patch, also what is it doing in rmap.c (I know hardly anything actually uses page_test_and_clear_young, but still). It seems to me like it only serves to make VM behaviour harder to understand, but I'm probably missing something. Andrew?
linux-2.6-npiggin/mm/filemap.c | 3 +-- linux-2.6-npiggin/mm/rmap.c | 2 +- linux-2.6-npiggin/mm/swap.c | 7 +------ 3 files changed, 3 insertions(+), 9 deletions(-)
mm/filemap.c renamed from mm/filemap.c~vm-dropbehind +1 -2
@@ -662,8 +662,7 @@ page_ok:/* * Mark the page accessed if we read the beginning. */ -if (!offset) -mark_page_accessed (page); +mark_page_accessed (page);/* * Ok, we have the page, and it's up-to-date, so
mm/swap.c renamed from mm/swap.c~vm-dropbehind +1 -6
@@ -111,13 +111,8 @@ void fastcall activate_page(struct page*/ void fastcall mark_page_accessed(struct page *page) { -if (!PageActiveMapped (page) && !PageActiveUnmapped (page) - &&PageReferenced (page) &&PageLRU (page)) { -activate_page (page); -ClearPageReferenced (page); - }else if (!PageReferenced (page)) { +if (!PageReferenced (page))SetPageReferenced (page); - } }EXPORT_SYMBOL (mark_page_accessed);
mm/rmap.c renamed from mm/rmap.c~vm-dropbehind +1 -1
@@ -118,7 +118,7 @@ int fastcall page_referenced(struct pageint referenced =0 ;if (page_test_and_clear_young (page)) -mark_page_accessed (page); + referenced++;if (TestClearPageReferenced (page)) referenced++;
_
Quoted 1 line · Nick Piggin
[...]
Quoted 6 lines
By the way, I would be interested to know the rationale behind
mark_page_accessedas it is without this patch, also what is it doing inrmap.c(I know hardly anything actually usespage_test_and_clear_young, but still). It seems to me like it only serves to make VM behaviour harder to understand, but I'm probably missing something. Andrew?
With your patch, once a page got into inactive list, its PG_referenced bit will only be checked by VM scanner when page wanders to the tail of list. In particular, if is impossible to tell pages that were accessed only once while on inactive list from ones that were accessed multiple times. Original mark_page_accessed() moves page to the active list on the second access, thus making it less eligible for the reclaim.
I actually tried quite an opposite modification:
(ftp://ftp.namesys.com/pub/misc-patches/unsupported/extra/2004.03.10-2.6.4-rc3/a_1[5678]*)
/* roughly, modulo locking, etc. */
void fastcall mark_page_accessed(struct page *page)
{
if (!PageReferenced(page))
SetPageReferenced(page);
else if (!PageLRU(page))
continue;
else if (!PageActive(page)) {
/* page is on inactive list */
del_page_from_inactive_list(zone, page);
SetPageActive(page);
add_page_to_active_list(zone, page);
inc_page_state(pgactivate);
ClearPageReferenced(page);
} else {
/* page is on active list, move it to head */
list_move(&page->lru, &zone->active_list);
ClearPageReferenced(page);
}
}That is, referenced and active page is moved to head of the active list. While somewhat improving file system performance it badly affects anonymous memory, because (it seems) file system pages tend to push mapped ones out of active list. Probably it should have better effect with your split active lists.
Quoted 1 line
Nikita.
Quoted 12 lines · Nikita Danilov
Quoted 1 line · Nick Piggin
[...]
Quoted 6 lines
By the way, I would be interested to know the rationale behind
mark_page_accessedas it is without this patch, also what is it doing inrmap.c(I know hardly anything actually usespage_test_and_clear_young, but still). It seems to me like it only serves to make VM behaviour harder to understand, but I'm probably missing something. Andrew?
Quoted 8 lines
With your patch, once a page got into inactive list, its
PG_referencedbit will only be checked by VM scanner when page wanders to the tail of list. In particular, if is impossible to tell pages that were accessed only once while on inactive list from ones that were accessed multiple times. Originalmark_page_accessed()moves page to the active list on the second access, thus making it less eligible for the reclaim.
With my patch though, it gives unmapped pages the same treatment as mapped pages. Without my patch, pages getting a lot of mark_page_accessed activity can easily be promoted unfairly past mapped ones which are simply getting activity through the pte.
I say just set the bit and let the scanner handle it.
Quoted 24 lines
I actually tried quite an opposite modification:
(ftp://ftp.namesys.com/pub/misc-patches/unsupported/extra/2004.03.10-2.6.4-rc3/a_1[5678]*)/* roughly, modulo locking, etc. */
void fastcallmark_page_accessed(struct page *page){ if (!PageReferenced(page)) SetPageReferenced(page); else if (!PageLRU(page)) continue; else if (!PageActive(page)) { /* page is on inactive list */ del_page_from_inactive_list(zone, page); SetPageActive(page); add_page_to_active_list(zone, page); inc_page_state(pgactivate); ClearPageReferenced(page); } else { /* page is on active list, move it to head */ list_move(&page->lru, &zone->active_list); ClearPageReferenced(page); } }
Quoted 6 lines
That is, referenced and active page is moved to head of the active list. While somewhat improving file system performance it badly affects anonymous memory, because (it seems) file system pages tend to push mapped ones out of active list. Probably it should have better effect with your split active lists.
Yeah. Hmm, I think it might be a good idea to do this sorting for unmapped pages on the active list. It shouldn't do ClearPageReferenced though, because your !PageReferenced pages now get their referenced bit set, and next time around the scanner they come in above the PageReferenced page.
I don't like the inactive->active promotion here though, as I explained.
Quoted 25 lines · Nick Piggin
Quoted 12 lines · Nikita Danilov
Quoted 1 line · Nick Piggin
[...]
Quoted 6 lines
By the way, I would be interested to know the rationale behind
mark_page_accessedas it is without this patch, also what is it doing inrmap.c(I know hardly anything actually usespage_test_and_clear_young, but still). It seems to me like it only serves to make VM behaviour harder to understand, but I'm probably missing something. Andrew?Quoted 8 lines
With your patch, once a page got into inactive list, its
PG_referencedbit will only be checked by VM scanner when page wanders to the tail of list. In particular, if is impossible to tell pages that were accessed only once while on inactive list from ones that were accessed multiple times. Originalmark_page_accessed()moves page to the active list on the second access, thus making it less eligible for the reclaim.
Quoted 4 lines
With my patch though, it gives unmapped pages the same treatment as mapped pages. Without my patch, pages getting a lot of
mark_page_accessedactivity can easily be promoted unfairly past mapped ones which are simply getting activity through the pte.
Another way to put it is that treatment of file system pages is dumbed down to the level of mapped ones: information about access patterns is just discarded.
Quoted 2 lines
I say just set the bit and let the scanner handle it.
I think that decisions about balancing VM and file system caches should be done by higher level, rather than by forcing file system to use low-level mechanisms designed for VM, where only limited information is provided by hardware. Splitting page queues is a step in a right direction, as it allows to implement more precise replacement for the file system cache.
Nikita.
Quoted 12 lines · Nikita Danilov
Quoted 4 lines · Nick Piggin
With my patch though, it gives unmapped pages the same treatment as mapped pages. Without my patch, pages getting a lot of
mark_page_accessedactivity can easily be promoted unfairly past mapped ones which are simply getting activity through the pte.Another way to put it is that treatment of file system pages is dumbed down to the level of mapped ones: information about access patterns is just discarded.
In a way, yes.
Quoted 11 lines
Quoted 2 lines
I say just set the bit and let the scanner handle it.
I think that decisions about balancing VM and file system caches should be done by higher level, rather than by forcing file system to use low-level mechanisms designed for VM, where only limited information is provided by hardware. Splitting page queues is a step in a right direction, as it allows to implement more precise replacement for the file system cache.
It makes it that much harder to calculate the pressure you are putting on mapped vs unmapped pages though.
Quoted 3 lines · Nick Piggin
Just had a try of doing things like updatedb and dd if=/dev/zero of=./blah It is pretty swappy I guess.
You'll need to bring the scanning priority back into the picture: don't move mapped pages down onto the inactive list at low scanning priorities. And that eans retaining the remember-the-priority-from-last-time logic.
Otherwise it's inevitable that even a `cat monster_file > /dev/null' will eventually swap out everything it can.
Quoted 5 lines
By the way, I would be interested to know the rationale behind
mark_page_accessedas it is without this patch, also what is it doing inrmap.c(I know hardly anything actually usespage_test_and_clear_young, but still). It seems to me like it only serves to make VM behaviour harder to understand, but I'm probably missing something. Andrew?
hm, that's left-over code which is pretty pointless now.
if (page_test_and_clear_young(page)) mark_page_accessed(page); if (TestClearPageReferenced(page)) referenced++;
The pages in here are never on the LRU, so all the mark_page_accessed() will do is to set PG_Referenced. And we immediately clear it again. So the mark_page_accessed() can be replaced with referenced++.
Quoted 6 lines · Andrew Morton
Quoted 3 lines · Nick Piggin
Just had a try of doing things like updatedb and dd if=/dev/zero of=./blah It is pretty swappy I guess.
Quoted 7 lines
You'll need to bring the scanning priority back into the picture: don't
move mapped pages down onto the inactive list at low scanning priorities. And that eans retaining the remember-the-priority-from-last-time logic.Otherwise it's inevitable that even a `cat
monster_file>/dev/null' will eventually swap out everything it can.
Hmm I dunno. At mapped_page_cost 8, I don't think it is swappy enough that your desktop users will be running into problems. I need to write 4GB of file to push out 70MB of swap here (256MB RAM). And not much of that swap has come back in, by the way...
Quoted 16 lines
Quoted 6 lines
By the way, I would be interested to know the rationale behind
mark_page_accessedas it is without this patch, also what is it doing inrmap.c(I know hardly anything actually usespage_test_and_clear_young, but still). It seems to me like it only serves to make VM behaviour harder to understand, but I'm probably missing something. Andrew?hm, that's left-over code which is pretty pointless now.
if (page_test_and_clear_young(page)) mark_page_accessed(page); if (TestClearPageReferenced(page)) referenced++;
Quoted 6 lines
The pages in here are never on the LRU, so all the
mark_page_accessed()will do is to setPG_Referenced. And we immediately clear it again. So themark_page_accessed()can be replaced with referenced++.
Yep, see the patch I'd attached before.
Quoted 26 lines · Nick Piggin
Quoted 11 lines · Matthias Urlichs
Quoted 3 lines · Andrew Morton
That effect is to cause the whole world to be swapped out when people return to their machines in the morning.
The correct solution to this problem is "suspend-to-disk" -- if the machine isn't doing anything anyway, TURN IT OFF.
Without arguing that point, the VM also should have a solution to the problem where people don't turn it off.
Quoted 6 lines
One slightly more practical solution from the "you-now-who gets angry mails" POV anyway, would be to tie the reduced-rate scanning to the load average -- if nothing at all happens, swap-out doesn't need to happen either.
Quoted 6 lines
Well if nothing at all happens we don't swap out, but when something is happening, desktop users don't want any of their programs to be swapped out no matter how long they have been sitting idle. They don't want to wait 10 seconds to page something in even if it means they're waiting an extra 10 minutes throughout the day for their kernel greps and diffs to finish.
I have noticed that 2.6 seems to clear memory (any version I've run for a while) and a lunch break results in a burst of disk activity before the screen saver even gets in to unlock the screen. I know this box has no cron activity during the day, so the pages were not forced out.
It's a good thing IMHO to write dirty pages to swap so the space can be reclaimed if needed, but shouldn't the page be marked as clean and left in memory for use without swap-in nif it's needed? I see this on backup servers, and a machine with 3GB of free memory, no mail, no cron and no app running isn't getting much memory pressure ;-)
I am not saying the behaviour is wrong, I just fail to see why the last application run isn't still in memory an hour later, absent memory pressure.
Signature · 1 line
-bill
Quoted 3 lines · Bill Davidsen
I have noticed that 2.6 seems to clear memory (any version I've run for a while) and a lunch break results in a burst of disk activity before the screen saver even gets in to unlock the screen. I know this box has no cron activity during the day, so the pages were not forced out.
It shouldn't. Perhaps something else is using memory in the background?
Quoted 2 lines
It's a good thing IMHO to write dirty pages to swap so the space can be reclaimed if needed, but shouldn't the page be marked as clean and left in memory for use without swap-in nif it's needed? I see this on backup servers, and a machine with 3GB of free memory, no mail, no cron and no app running isn't getting much memory pressure ;-)
Well it is basically just written out and reclaimed when it is needed, it won't just be swapped out without memory pressure.
Although, there were some highmem balancing problems in 2.6 including 2.6.4 (now fixed in -bk). This causes too much pressure to be put on ZONE_NORMAL mapped and file cache memory in favour of slab cache. This could easily be causing the misbehaviour.
Quoted 2 lines
I am not saying the behaviour is wrong, I just fail to see why the last application run isn't still in memory an hour later, absent memory pressure.
There would have to be *some* memory pressure... honestly, try 2.6-bk, or if they are production machines and you can't, then wait for 2.6.5.
Hi!
Quoted 5 lines
Quoted 2 lines
That effect is to cause the whole world to be swapped out when people return to their machines in the morning.
The correct solution to this problem is "suspend-to-disk" -- if the machine isn't doing anything anyway, TURN IT OFF.
Try it.
With current design, machine swaps *a lot* after resume.
Suspend-to-ram is probably better.
But if you don't run your updatedb overnight, you are going to run it while you are logged in, and that is going to suck.
Signature · 1 line
64 bytes from 195.113.31.123: icmp_seq=28 ttl=51 time=448769.1 ms