diff mbox

[5/5] vmscan: Age anonymous memory even when swap is off.

Message ID 1395436655-21670-6-git-send-email-john.stultz@linaro.org
State Superseded
Headers show

Commit Message

John Stultz March 21, 2014, 9:17 p.m. UTC
Currently we don't shrink/scan the anonymous lrus when swap is off.
This is problematic for volatile range purging on swapless systems/

This patch naievely changes the vmscan code to continue scanning
and shrinking the lrus even when there is no swap.

It obviously has performance issues.

Thoughts on how best to implement this would be appreciated.

Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Android Kernel Team <kernel-team@android.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Robert Love <rlove@google.com>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Hugh Dickins <hughd@google.com>
Cc: Dave Hansen <dave@sr71.net>
Cc: Rik van Riel <riel@redhat.com>
Cc: Dmitry Adamushko <dmitry.adamushko@gmail.com>
Cc: Neil Brown <neilb@suse.de>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Mike Hommey <mh@glandium.org>
Cc: Taras Glek <tglek@mozilla.com>
Cc: Jan Kara <jack@suse.cz>
Cc: KOSAKI Motohiro <kosaki.motohiro@gmail.com>
Cc: Michel Lespinasse <walken@google.com>
Cc: Minchan Kim <minchan@kernel.org>
Cc: linux-mm@kvack.org <linux-mm@kvack.org>
Signed-off-by: John Stultz <john.stultz@linaro.org>
---
 mm/vmscan.c | 26 ++++----------------------
 1 file changed, 4 insertions(+), 22 deletions(-)

Comments

Rik van Riel March 24, 2014, 5:33 p.m. UTC | #1
On 03/21/2014 05:17 PM, John Stultz wrote:
> Currently we don't shrink/scan the anonymous lrus when swap is off.
> This is problematic for volatile range purging on swapless systems/
>
> This patch naievely changes the vmscan code to continue scanning
> and shrinking the lrus even when there is no swap.
>
> It obviously has performance issues.
>
> Thoughts on how best to implement this would be appreciated.
>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Android Kernel Team <kernel-team@android.com>
> Cc: Johannes Weiner <hannes@cmpxchg.org>
> Cc: Robert Love <rlove@google.com>
> Cc: Mel Gorman <mel@csn.ul.ie>
> Cc: Hugh Dickins <hughd@google.com>
> Cc: Dave Hansen <dave@sr71.net>
> Cc: Rik van Riel <riel@redhat.com>
> Cc: Dmitry Adamushko <dmitry.adamushko@gmail.com>
> Cc: Neil Brown <neilb@suse.de>
> Cc: Andrea Arcangeli <aarcange@redhat.com>
> Cc: Mike Hommey <mh@glandium.org>
> Cc: Taras Glek <tglek@mozilla.com>
> Cc: Jan Kara <jack@suse.cz>
> Cc: KOSAKI Motohiro <kosaki.motohiro@gmail.com>
> Cc: Michel Lespinasse <walken@google.com>
> Cc: Minchan Kim <minchan@kernel.org>
> Cc: linux-mm@kvack.org <linux-mm@kvack.org>
> Signed-off-by: John Stultz <john.stultz@linaro.org>
> ---
>   mm/vmscan.c | 26 ++++----------------------
>   1 file changed, 4 insertions(+), 22 deletions(-)
>
> diff --git a/mm/vmscan.c b/mm/vmscan.c
> index 34f159a..07b0a8c 100644
> --- a/mm/vmscan.c
> +++ b/mm/vmscan.c
> @@ -155,9 +155,8 @@ static unsigned long zone_reclaimable_pages(struct zone *zone)
>   	nr = zone_page_state(zone, NR_ACTIVE_FILE) +
>   	     zone_page_state(zone, NR_INACTIVE_FILE);
>
> -	if (get_nr_swap_pages() > 0)
> -		nr += zone_page_state(zone, NR_ACTIVE_ANON) +
> -		      zone_page_state(zone, NR_INACTIVE_ANON);
> +	nr += zone_page_state(zone, NR_ACTIVE_ANON) +
> +	      zone_page_state(zone, NR_INACTIVE_ANON);
>
>   	return nr;

Not all of the anonymous pages will be reclaimable.

Is there some counter that keeps track of how many
volatile range pages there are in each zone?


> @@ -1764,13 +1763,6 @@ static int inactive_anon_is_low_global(struct zone *zone)
>    */
>   static int inactive_anon_is_low(struct lruvec *lruvec)
>   {
> -	/*
> -	 * If we don't have swap space, anonymous page deactivation
> -	 * is pointless.
> -	 */
> -	if (!total_swap_pages)
> -		return 0;
> -
>   	if (!mem_cgroup_disabled())
>   		return mem_cgroup_inactive_anon_is_low(lruvec);

This part is correct, and needed.

> @@ -1880,12 +1872,6 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc,
>   	if (!global_reclaim(sc))
>   		force_scan = true;
>
> -	/* If we have no swap space, do not bother scanning anon pages. */
> -	if (!sc->may_swap || (get_nr_swap_pages() <= 0)) {
> -		scan_balance = SCAN_FILE;
> -		goto out;
> -	}
> -
>   	/*

This part is too.

> @@ -2181,8 +2166,8 @@ static inline bool should_continue_reclaim(struct zone *zone,
>   	 */
>   	pages_for_compaction = (2UL << sc->order);
>   	inactive_lru_pages = zone_page_state(zone, NR_INACTIVE_FILE);
> -	if (get_nr_swap_pages() > 0)
> -		inactive_lru_pages += zone_page_state(zone, NR_INACTIVE_ANON);
> +	inactive_lru_pages += zone_page_state(zone, NR_INACTIVE_ANON);
> +
>   	if (sc->nr_reclaimed < pages_for_compaction &&
>   			inactive_lru_pages > pages_for_compaction)

Not sure this is a good idea, since the pages may not actually
be reclaimable, and the inactive list will continue to be
refilled indefinitely...

If there was a counter of the number of volatile range pages
in a zone, this would be easier.

Of course, the overhead of keeping such a counter might be
too high for what volatile ranges are designed for...

>   		return true;
> @@ -2726,9 +2711,6 @@ static void age_active_anon(struct zone *zone, struct scan_control *sc)
>   {
>   	struct mem_cgroup *memcg;
>
> -	if (!total_swap_pages)
> -		return;
> -

This bit is correct and needed.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
John Stultz March 24, 2014, 6:04 p.m. UTC | #2
On Mon, Mar 24, 2014 at 10:33 AM, Rik van Riel <riel@redhat.com> wrote:
> On 03/21/2014 05:17 PM, John Stultz wrote:
>>
>> Currently we don't shrink/scan the anonymous lrus when swap is off.
>> This is problematic for volatile range purging on swapless systems/
>>
>> This patch naievely changes the vmscan code to continue scanning
>> and shrinking the lrus even when there is no swap.
>>
>> It obviously has performance issues.
>>
>> Thoughts on how best to implement this would be appreciated.
>>
>> Cc: Andrew Morton <akpm@linux-foundation.org>
>> Cc: Android Kernel Team <kernel-team@android.com>
>> Cc: Johannes Weiner <hannes@cmpxchg.org>
>> Cc: Robert Love <rlove@google.com>
>> Cc: Mel Gorman <mel@csn.ul.ie>
>> Cc: Hugh Dickins <hughd@google.com>
>> Cc: Dave Hansen <dave@sr71.net>
>> Cc: Rik van Riel <riel@redhat.com>
>> Cc: Dmitry Adamushko <dmitry.adamushko@gmail.com>
>> Cc: Neil Brown <neilb@suse.de>
>> Cc: Andrea Arcangeli <aarcange@redhat.com>
>> Cc: Mike Hommey <mh@glandium.org>
>> Cc: Taras Glek <tglek@mozilla.com>
>> Cc: Jan Kara <jack@suse.cz>
>> Cc: KOSAKI Motohiro <kosaki.motohiro@gmail.com>
>> Cc: Michel Lespinasse <walken@google.com>
>> Cc: Minchan Kim <minchan@kernel.org>
>> Cc: linux-mm@kvack.org <linux-mm@kvack.org>
>> Signed-off-by: John Stultz <john.stultz@linaro.org>
>> ---
>>   mm/vmscan.c | 26 ++++----------------------
>>   1 file changed, 4 insertions(+), 22 deletions(-)
>>
>> diff --git a/mm/vmscan.c b/mm/vmscan.c
>> index 34f159a..07b0a8c 100644
>> --- a/mm/vmscan.c
>> +++ b/mm/vmscan.c
>> @@ -155,9 +155,8 @@ static unsigned long zone_reclaimable_pages(struct
>> zone *zone)
>>         nr = zone_page_state(zone, NR_ACTIVE_FILE) +
>>              zone_page_state(zone, NR_INACTIVE_FILE);
>>
>> -       if (get_nr_swap_pages() > 0)
>> -               nr += zone_page_state(zone, NR_ACTIVE_ANON) +
>> -                     zone_page_state(zone, NR_INACTIVE_ANON);
>> +       nr += zone_page_state(zone, NR_ACTIVE_ANON) +
>> +             zone_page_state(zone, NR_INACTIVE_ANON);
>>
>>         return nr;
>
>
> Not all of the anonymous pages will be reclaimable.
>
> Is there some counter that keeps track of how many
> volatile range pages there are in each zone?

So right, keeping statistics like NR_VOLATILE_PAGES (as well as
possibly NR_PURGED_VOLATILE_PAGES), would likely help here.

>> @@ -2181,8 +2166,8 @@ static inline bool should_continue_reclaim(struct
>> zone *zone,
>>          */
>>         pages_for_compaction = (2UL << sc->order);
>>         inactive_lru_pages = zone_page_state(zone, NR_INACTIVE_FILE);
>> -       if (get_nr_swap_pages() > 0)
>> -               inactive_lru_pages += zone_page_state(zone,
>> NR_INACTIVE_ANON);
>> +       inactive_lru_pages += zone_page_state(zone, NR_INACTIVE_ANON);
>> +
>>         if (sc->nr_reclaimed < pages_for_compaction &&
>>                         inactive_lru_pages > pages_for_compaction)
>
>
> Not sure this is a good idea, since the pages may not actually
> be reclaimable, and the inactive list will continue to be
> refilled indefinitely...
>
> If there was a counter of the number of volatile range pages
> in a zone, this would be easier.
>
> Of course, the overhead of keeping such a counter might be
> too high for what volatile ranges are designed for...

I started looking at something like this, but it runs into some
complexity when we're keeping volatility as a flag in the vma rather
then as a page state.

Also, even with a rough attempt at tracking of the number of volatile
pages, it seemed naively plugging that in for NR_INACTIVE_ANON here
was problematic, since we would scan for a shorter time, but but
wouldn't necessarily find the volatile pages in that time, causing us
not to always purge the volatile pages.

Part of me starts to wonder if a new LRU for volatile pages would be
needed to really be efficient here, but then I worry the moving of the
pages back and forth might be too expensive.

Thanks so much for the review and comments!
-john
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
diff mbox

Patch

diff --git a/mm/vmscan.c b/mm/vmscan.c
index 34f159a..07b0a8c 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -155,9 +155,8 @@  static unsigned long zone_reclaimable_pages(struct zone *zone)
 	nr = zone_page_state(zone, NR_ACTIVE_FILE) +
 	     zone_page_state(zone, NR_INACTIVE_FILE);
 
-	if (get_nr_swap_pages() > 0)
-		nr += zone_page_state(zone, NR_ACTIVE_ANON) +
-		      zone_page_state(zone, NR_INACTIVE_ANON);
+	nr += zone_page_state(zone, NR_ACTIVE_ANON) +
+	      zone_page_state(zone, NR_INACTIVE_ANON);
 
 	return nr;
 }
@@ -1764,13 +1763,6 @@  static int inactive_anon_is_low_global(struct zone *zone)
  */
 static int inactive_anon_is_low(struct lruvec *lruvec)
 {
-	/*
-	 * If we don't have swap space, anonymous page deactivation
-	 * is pointless.
-	 */
-	if (!total_swap_pages)
-		return 0;
-
 	if (!mem_cgroup_disabled())
 		return mem_cgroup_inactive_anon_is_low(lruvec);
 
@@ -1880,12 +1872,6 @@  static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc,
 	if (!global_reclaim(sc))
 		force_scan = true;
 
-	/* If we have no swap space, do not bother scanning anon pages. */
-	if (!sc->may_swap || (get_nr_swap_pages() <= 0)) {
-		scan_balance = SCAN_FILE;
-		goto out;
-	}
-
 	/*
 	 * Global reclaim will swap to prevent OOM even with no
 	 * swappiness, but memcg users want to use this knob to
@@ -2048,7 +2034,6 @@  static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)
 			if (nr[lru]) {
 				nr_to_scan = min(nr[lru], SWAP_CLUSTER_MAX);
 				nr[lru] -= nr_to_scan;
-
 				nr_reclaimed += shrink_list(lru, nr_to_scan,
 							    lruvec, sc);
 			}
@@ -2181,8 +2166,8 @@  static inline bool should_continue_reclaim(struct zone *zone,
 	 */
 	pages_for_compaction = (2UL << sc->order);
 	inactive_lru_pages = zone_page_state(zone, NR_INACTIVE_FILE);
-	if (get_nr_swap_pages() > 0)
-		inactive_lru_pages += zone_page_state(zone, NR_INACTIVE_ANON);
+	inactive_lru_pages += zone_page_state(zone, NR_INACTIVE_ANON);
+
 	if (sc->nr_reclaimed < pages_for_compaction &&
 			inactive_lru_pages > pages_for_compaction)
 		return true;
@@ -2726,9 +2711,6 @@  static void age_active_anon(struct zone *zone, struct scan_control *sc)
 {
 	struct mem_cgroup *memcg;
 
-	if (!total_swap_pages)
-		return;
-
 	memcg = mem_cgroup_iter(NULL, NULL, NULL);
 	do {
 		struct lruvec *lruvec = mem_cgroup_zone_lruvec(zone, memcg);