History

mm: base LRU balancing on an explicit cost model

Currently, scan pressure between the anon and file LRU lists is balanced based on a mixture of reclaim efficiency and a somewhat vague notion of "value" of having certain pages in memory over others. That concept of value is problematic, because it has caused us to count any event that remotely makes one LRU list more or less preferrable for reclaim, even when these events are not directly comparable and impose very different costs on the system. One example is referenced file pages that we still deactivate and referenced anonymous pages that we actually rotate back to the head of the list. There is also conceptual overlap with the LRU algorithm itself. By rotating recently used pages instead of reclaiming them, the algorithm already biases the applied scan pressure based on page value. Thus, when rebalancing scan pressure due to rotations, we should think of reclaim cost, and leave assessing the page value to the LRU algorithm. Lastly, considering both value-increasing as well as value-decreasing events can sometimes cause the same type of event to be counted twice, i.e. how rotating a page increases the LRU value, while reclaiming it succesfully decreases the value. In itself this will balance out fine, but it quietly skews the impact of events that are only recorded once. The abstract metric of "value", the murky relationship with the LRU algorithm, and accounting both negative and positive events make the current pressure balancing model hard to reason about and modify. This patch switches to a balancing model of accounting the concrete, actually observed cost of reclaiming one LRU over another. For now, that cost includes pages that are scanned but rotated back to the list head. Subsequent patches will add consideration for IO caused by refaulting of recently evicted pages. Replace struct zone_reclaim_stat with two cost counters in the lruvec, and make everything that affects cost go through a new lru_note_cost() function.

Johannes Weiner committed 6 years ago

Commit 1431d4d1 parent a4fe1635 files · +45 −59Browse files

Showing the changes to include/linux (2 of 5 files). Show all

Unified · Split

2 files
  1. include/linux/mmzone.h +7 −14
  2. include/linux/swap.h +2 −0
include/linux/mmzone.h+7−14
@@ -242,19 +242,6 @@ static inline bool is_active_lru(enum lru_list lru) · 241 unmodified lines
242 return (lru == LRU_ACTIVE_ANON || lru == LRU_ACTIVE_FILE);242 return (lru == LRU_ACTIVE_ANON || lru == LRU_ACTIVE_FILE);
243}243}
244 244
245struct zone_reclaim_stat {
246 /*
247 * The pageout code in vmscan.c keeps track of how many of the
248 * mem/swap backed and file backed pages are referenced.
249 * The higher the rotated/scanned ratio, the more valuable
250 * that cache is.
251 *
252 * The anon LRU stats live in [0], file LRU stats in [1]
253 */
254 unsigned long recent_rotated[2];
255 unsigned long recent_scanned[2];
256};
257
258enum lruvec_flags {245enum lruvec_flags {
259 LRUVEC_CONGESTED, /* lruvec has many dirty pages246 LRUVEC_CONGESTED, /* lruvec has many dirty pages
260 * backed by a congested BDI247 * backed by a congested BDI
@@ -263,7 +250,13 @@ enum lruvec_flags { · 2 unmodified lines
263 250
264struct lruvec {251struct lruvec {
265 struct list_head lists[NR_LRU_LISTS];252 struct list_head lists[NR_LRU_LISTS];
266 struct zone_reclaim_stat reclaim_stat;253 /*
254 * These track the cost of reclaiming one LRU - file or anon -
255 * over the other. As the observed cost of reclaiming one LRU
256 * increases, the reclaim scan balance tips toward the other.
257 */
258 unsigned long anon_cost;
259 unsigned long file_cost;
267 /* Evictions & activations on the inactive file list */260 /* Evictions & activations on the inactive file list */
268 atomic_long_t inactive_age;261 atomic_long_t inactive_age;
269 /* Refaults at the time of last reclaim cycle */262 /* Refaults at the time of last reclaim cycle */
include/linux/swap.h+2−0
@@ -334,6 +334,8 @@ extern unsigned long nr_free_pagecache_pages(void); · 333 unmodified lines
334 334
335 335
336/* linux/mm/swap.c */336/* linux/mm/swap.c */
337extern void lru_note_cost(struct lruvec *lruvec, bool file,
338 unsigned int nr_pages);
337extern void lru_cache_add(struct page *);339extern void lru_cache_add(struct page *);
338extern void lru_add_page_tail(struct page *page, struct page *page_tail,340extern void lru_add_page_tail(struct page *page, struct page *page_tail,
339 struct lruvec *lruvec, struct list_head *head);341 struct lruvec *lruvec, struct list_head *head);