aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorSergey Senozhatsky <sergey.senozhatsky@gmail.com>2015-09-08 18:04:27 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-09-08 18:35:28 -0400
commit57244594195fe697f9261c7970ca25db35280967 (patch)
treef62a914de0e1ac2d7dd7de44d866a90c26369302 /mm
parentb430d1fd6c7d22cc07e7c22a2ee1078667605313 (diff)
zsmalloc: always keep per-class stats
Always account per-class `zs_size_stat' stats. This data will help us make better decisions during compaction. We are especially interested in OBJ_ALLOCATED and OBJ_USED, which can tell us if class compaction will result in any memory gain. For instance, we know the number of allocated objects in the class, the number of objects being used (so we also know how many objects are not used) and the number of objects per-page. So we can ensure if we have enough unused objects to form at least one ZS_EMPTY zspage during compaction. We calculate this value on per-class basis so we can calculate a total number of zspages that can be released. Which is exactly what a shrinker wants to know. Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com> Acked-by: Minchan Kim <minchan@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/zsmalloc.c40
1 files changed, 8 insertions, 32 deletions
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index 7d816c2d74f9..1227f8323e93 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -169,14 +169,12 @@ enum zs_stat_type {
169 NR_ZS_STAT_TYPE, 169 NR_ZS_STAT_TYPE,
170}; 170};
171 171
172#ifdef CONFIG_ZSMALLOC_STAT
173
174static struct dentry *zs_stat_root;
175
176struct zs_size_stat { 172struct zs_size_stat {
177 unsigned long objs[NR_ZS_STAT_TYPE]; 173 unsigned long objs[NR_ZS_STAT_TYPE];
178}; 174};
179 175
176#ifdef CONFIG_ZSMALLOC_STAT
177static struct dentry *zs_stat_root;
180#endif 178#endif
181 179
182/* 180/*
@@ -201,6 +199,8 @@ static int zs_size_classes;
201static const int fullness_threshold_frac = 4; 199static const int fullness_threshold_frac = 4;
202 200
203struct size_class { 201struct size_class {
202 spinlock_t lock;
203 struct page *fullness_list[_ZS_NR_FULLNESS_GROUPS];
204 /* 204 /*
205 * Size of objects stored in this class. Must be multiple 205 * Size of objects stored in this class. Must be multiple
206 * of ZS_ALIGN. 206 * of ZS_ALIGN.
@@ -210,16 +210,10 @@ struct size_class {
210 210
211 /* Number of PAGE_SIZE sized pages to combine to form a 'zspage' */ 211 /* Number of PAGE_SIZE sized pages to combine to form a 'zspage' */
212 int pages_per_zspage; 212 int pages_per_zspage;
213 /* huge object: pages_per_zspage == 1 && maxobj_per_zspage == 1 */
214 bool huge;
215
216#ifdef CONFIG_ZSMALLOC_STAT
217 struct zs_size_stat stats; 213 struct zs_size_stat stats;
218#endif
219
220 spinlock_t lock;
221 214
222 struct page *fullness_list[_ZS_NR_FULLNESS_GROUPS]; 215 /* huge object: pages_per_zspage == 1 && maxobj_per_zspage == 1 */
216 bool huge;
223}; 217};
224 218
225/* 219/*
@@ -441,8 +435,6 @@ static int get_size_class_index(int size)
441 return min(zs_size_classes - 1, idx); 435 return min(zs_size_classes - 1, idx);
442} 436}
443 437
444#ifdef CONFIG_ZSMALLOC_STAT
445
446static inline void zs_stat_inc(struct size_class *class, 438static inline void zs_stat_inc(struct size_class *class,
447 enum zs_stat_type type, unsigned long cnt) 439 enum zs_stat_type type, unsigned long cnt)
448{ 440{
@@ -461,6 +453,8 @@ static inline unsigned long zs_stat_get(struct size_class *class,
461 return class->stats.objs[type]; 453 return class->stats.objs[type];
462} 454}
463 455
456#ifdef CONFIG_ZSMALLOC_STAT
457
464static int __init zs_stat_init(void) 458static int __init zs_stat_init(void)
465{ 459{
466 if (!debugfs_initialized()) 460 if (!debugfs_initialized())
@@ -576,23 +570,6 @@ static void zs_pool_stat_destroy(struct zs_pool *pool)
576} 570}
577 571
578#else /* CONFIG_ZSMALLOC_STAT */ 572#else /* CONFIG_ZSMALLOC_STAT */
579
580static inline void zs_stat_inc(struct size_class *class,
581 enum zs_stat_type type, unsigned long cnt)
582{
583}
584
585static inline void zs_stat_dec(struct size_class *class,
586 enum zs_stat_type type, unsigned long cnt)
587{
588}
589
590static inline unsigned long zs_stat_get(struct size_class *class,
591 enum zs_stat_type type)
592{
593 return 0;
594}
595
596static int __init zs_stat_init(void) 573static int __init zs_stat_init(void)
597{ 574{
598 return 0; 575 return 0;
@@ -610,7 +587,6 @@ static inline int zs_pool_stat_create(char *name, struct zs_pool *pool)
610static inline void zs_pool_stat_destroy(struct zs_pool *pool) 587static inline void zs_pool_stat_destroy(struct zs_pool *pool)
611{ 588{
612} 589}
613
614#endif 590#endif
615 591
616 592