History

mm: memcg: factor out memcg- and lruvec-level changes out of __mod_lruvec_state()

Patch series "The new cgroup slab memory controller", v7. The patchset moves the accounting from the page level to the object level. It allows to share slab pages between memory cgroups. This leads to a significant win in the slab utilization (up to 45%) and the corresponding drop in the total kernel memory footprint. The reduced number of unmovable slab pages should also have a positive effect on the memory fragmentation. The patchset makes the slab accounting code simpler: there is no more need in the complicated dynamic creation and destruction of per-cgroup slab caches, all memory cgroups use a global set of shared slab caches. The lifetime of slab caches is not more connected to the lifetime of memory cgroups. The more precise accounting does require more CPU, however in practice the difference seems to be negligible. We've been using the new slab controller in Facebook production for several months with different workloads and haven't seen any noticeable regressions. What we've seen were memory savings in order of 1 GB per host (it varied heavily depending on the actual workload, size of RAM, number of CPUs, memory pressure, etc). The third version of the patchset added yet another step towards the simplification of the code: sharing of slab caches between accounted and non-accounted allocations. It comes with significant upsides (most noticeable, a complete elimination of dynamic slab caches creation) but not without some regression risks, so this change sits on top of the patchset and is not completely merged in. So in the unlikely event of a noticeable performance regression it can be reverted separately. The slab memory accounting works in exactly the same way for SLAB and SLUB. With both allocators the new controller shows significant memory savings, with SLUB the difference is bigger. On my 16-core desktop machine running Fedora 32 the size of the slab memory measured after the start of the system was lower by 58% and 38% with SLUB and SLAB correspondingly. As an estimation of a potential CPU overhead, below are results of slab_bulk_test01 test, kindly provided by Jesper D. Brouer. He also helped with the evaluation of results. The test can be found here: https://github.com/netoptimizer/prototype-kernel/ The smallest number in each row should be picked for a comparison. SLUB-patched - bulk-API - SLUB-patched : bulk_quick_reuse objects=1 : 187 - 90 - 224 cycles(tsc) - SLUB-patched : bulk_quick_reuse objects=2 : 110 - 53 - 133 cycles(tsc) - SLUB-patched : bulk_quick_reuse objects=3 : 88 - 95 - 42 cycles(tsc) - SLUB-patched : bulk_quick_reuse objects=4 : 91 - 85 - 36 cycles(tsc) - SLUB-patched : bulk_quick_reuse objects=8 : 32 - 66 - 32 cycles(tsc) SLUB-original - bulk-API - SLUB-original: bulk_quick_reuse objects=1 : 87 - 87 - 142 cycles(tsc) - SLUB-original: bulk_quick_reuse objects=2 : 52 - 53 - 53 cycles(tsc) - SLUB-original: bulk_quick_reuse objects=3 : 42 - 42 - 91 cycles(tsc) - SLUB-original: bulk_quick_reuse objects=4 : 91 - 37 - 37 cycles(tsc) - SLUB-original: bulk_quick_reuse objects=8 : 31 - 79 - 76 cycles(tsc) SLAB-patched - bulk-API - SLAB-patched : bulk_quick_reuse objects=1 : 67 - 67 - 140 cycles(tsc) - SLAB-patched : bulk_quick_reuse objects=2 : 55 - 46 - 46 cycles(tsc) - SLAB-patched : bulk_quick_reuse objects=3 : 93 - 94 - 39 cycles(tsc) - SLAB-patched : bulk_quick_reuse objects=4 : 35 - 88 - 85 cycles(tsc) - SLAB-patched : bulk_quick_reuse objects=8 : 30 - 30 - 30 cycles(tsc) SLAB-original- bulk-API - SLAB-original: bulk_quick_reuse objects=1 : 143 - 136 - 67 cycles(tsc) - SLAB-original: bulk_quick_reuse objects=2 : 45 - 46 - 46 cycles(tsc) - SLAB-original: bulk_quick_reuse objects=3 : 38 - 39 - 39 cycles(tsc) - SLAB-original: bulk_quick_reuse objects=4 : 35 - 87 - 87 cycles(tsc) - SLAB-original: bulk_quick_reuse objects=8 : 29 - 66 - 30 cycles(tsc) This patch (of 19): To convert memcg and lruvec slab counters to bytes there must be a way to change these counters without touching node counters. Factor out __mod_memcg_lruvec_state() out of __mod_lruvec_state().

Roman Gushchin committed 6 years ago

Commit eedc4e51 parent d648bcc2 files · +41 −19Browse files

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

Unified · Split

include/linux/memcontrol.h+17−0
@@ -679,11 +679,23 @@ static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec, · 678 unmodified lines
679 return x;679 return x;
680}680}
681 681
682void __mod_memcg_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,
683 int val);
682void __mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,684void __mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,
683 int val);685 int val);
684void __mod_lruvec_slab_state(void *p, enum node_stat_item idx, int val);686void __mod_lruvec_slab_state(void *p, enum node_stat_item idx, int val);
685void mod_memcg_obj_state(void *p, int idx, int val);687void mod_memcg_obj_state(void *p, int idx, int val);
686 688
689static inline void mod_memcg_lruvec_state(struct lruvec *lruvec,
690 enum node_stat_item idx, int val)
691{
692 unsigned long flags;
693
694 local_irq_save(flags);
695 __mod_memcg_lruvec_state(lruvec, idx, val);
696 local_irq_restore(flags);
697}
698
687static inline void mod_lruvec_state(struct lruvec *lruvec,699static inline void mod_lruvec_state(struct lruvec *lruvec,
688 enum node_stat_item idx, int val)700 enum node_stat_item idx, int val)
689{701{
@@ -1057,6 +1069,11 @@ static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec, · 367 unmodified lines
1057 return node_page_state(lruvec_pgdat(lruvec), idx);1069 return node_page_state(lruvec_pgdat(lruvec), idx);
1058}1070}
1059 1071
1072static inline void __mod_memcg_lruvec_state(struct lruvec *lruvec,
1073 enum node_stat_item idx, int val)
1074{
1075}
1076
1060static inline void __mod_lruvec_state(struct lruvec *lruvec,1077static inline void __mod_lruvec_state(struct lruvec *lruvec,
1061 enum node_stat_item idx, int val)1078 enum node_stat_item idx, int val)
1062{1079{