Message ID | 1584500541-46817-1-git-send-email-yang.shi@linux.alibaba.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v4,1/2] mm: swap: make page_evictable() inline | expand |
On Wed, Mar 18, 2020 at 11:02:20AM +0800, Yang Shi wrote: > Fixes: 9c4e6b1a7027 ("mm, mlock, vmscan: no more skipping pagevecs") > Cc: Matthew Wilcox <willy@infradead.org> > Reviewed-and-Tested-by: Shakeel Butt <shakeelb@google.com> > Acked-by: Vlastimil Babka <vbabka@suse.cz> > Signed-off-by: Yang Shi <yang.shi@linux.alibaba.com> Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
On Wed, Mar 18, 2020 at 11:02:20AM +0800, Yang Shi wrote: > When backporting commit 9c4e6b1a7027 ("mm, mlock, vmscan: no more > skipping pagevecs") to our 4.9 kernel, our test bench noticed around 10% > down with a couple of vm-scalability's test cases (lru-file-readonce, > lru-file-readtwice and lru-file-mmap-read). I didn't see that much down > on my VM (32c-64g-2nodes). It might be caused by the test configuration, > which is 32c-256g with NUMA disabled and the tests were run in root memcg, > so the tests actually stress only one inactive and active lru. It > sounds not very usual in mordern production environment. > > That commit did two major changes: > 1. Call page_evictable() > 2. Use smp_mb to force the PG_lru set visible > > It looks they contribute the most overhead. The page_evictable() is a > function which does function prologue and epilogue, and that was used by > page reclaim path only. However, lru add is a very hot path, so it > sounds better to make it inline. However, it calls page_mapping() which > is not inlined either, but the disassemble shows it doesn't do push and > pop operations and it sounds not very straightforward to inline it. > > Other than this, it sounds smp_mb() is not necessary for x86 since > SetPageLRU is atomic which enforces memory barrier already, replace it > with smp_mb__after_atomic() in the following patch. > > With the two fixes applied, the tests can get back around 5% on that > test bench and get back normal on my VM. Since the test bench > configuration is not that usual and I also saw around 6% up on the > latest upstream, so it sounds good enough IMHO. > > The below is test data (lru-file-readtwice throughput) against the v5.6-rc4: > mainline w/ inline fix > 150MB 154MB > > With this patch the throughput gets 2.67% up. The data with using > smp_mb__after_atomic() is showed in the following patch. > > Shakeel Butt did the below test: > > On a real machine with limiting the 'dd' on a single node and reading 100 GiB > sparse file (less than a single node). Just ran a single instance to not > cause the lru lock contention. The cmdline used is > "dd if=file-100GiB of=/dev/null bs=4k". Ran the cmd 10 times with drop_caches > in between and measured the time it took. > > Without patch: 56.64143 +- 0.672 sec > > With patches: 56.10 +- 0.21 sec > > Fixes: 9c4e6b1a7027 ("mm, mlock, vmscan: no more skipping pagevecs") > Cc: Matthew Wilcox <willy@infradead.org> > Reviewed-and-Tested-by: Shakeel Butt <shakeelb@google.com> > Acked-by: Vlastimil Babka <vbabka@suse.cz> > Signed-off-by: Yang Shi <yang.shi@linux.alibaba.com> Acked-by: Johannes Weiner <hannes@cmpxchg.org>
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index ccb14b6..82c2127 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -70,11 +70,9 @@ static inline void mapping_clear_unevictable(struct address_space *mapping) clear_bit(AS_UNEVICTABLE, &mapping->flags); } -static inline int mapping_unevictable(struct address_space *mapping) +static inline bool mapping_unevictable(struct address_space *mapping) { - if (mapping) - return test_bit(AS_UNEVICTABLE, &mapping->flags); - return !!mapping; + return mapping && test_bit(AS_UNEVICTABLE, &mapping->flags); } static inline void mapping_set_exiting(struct address_space *mapping) @@ -118,6 +116,29 @@ static inline void mapping_set_gfp_mask(struct address_space *m, gfp_t mask) m->gfp_mask = mask; } +/** + * page_evictable - test whether a page is evictable + * @page: the page to test + * + * Test whether page is evictable--i.e., should be placed on active/inactive + * lists vs unevictable list. + * + * Reasons page might not be evictable: + * (1) page's mapping marked unevictable + * (2) page is part of an mlocked VMA + * + */ +static inline bool page_evictable(struct page *page) +{ + bool ret; + + /* Prevent address_space of inode and swap cache from being freed */ + rcu_read_lock(); + ret = !mapping_unevictable(page_mapping(page)) && !PageMlocked(page); + rcu_read_unlock(); + return ret; +} + void release_pages(struct page **pages, int nr); /* diff --git a/include/linux/swap.h b/include/linux/swap.h index 1e99f7a..b835d8d 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -374,7 +374,6 @@ extern unsigned long mem_cgroup_shrink_node(struct mem_cgroup *mem, #define node_reclaim_mode 0 #endif -extern int page_evictable(struct page *page); extern void check_move_unevictable_pages(struct pagevec *pvec); extern int kswapd_run(int nid); diff --git a/mm/vmscan.c b/mm/vmscan.c index 8763705..855c395 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -4277,29 +4277,6 @@ int node_reclaim(struct pglist_data *pgdat, gfp_t gfp_mask, unsigned int order) } #endif -/* - * page_evictable - test whether a page is evictable - * @page: the page to test - * - * Test whether page is evictable--i.e., should be placed on active/inactive - * lists vs unevictable list. - * - * Reasons page might not be evictable: - * (1) page's mapping marked unevictable - * (2) page is part of an mlocked VMA - * - */ -int page_evictable(struct page *page) -{ - int ret; - - /* Prevent address_space of inode and swap cache from being freed */ - rcu_read_lock(); - ret = !mapping_unevictable(page_mapping(page)) && !PageMlocked(page); - rcu_read_unlock(); - return ret; -} - /** * check_move_unevictable_pages - check pages for evictability and move to * appropriate zone lru list