diff options
author | Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com> | 2015-11-06 19:29:38 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-06 20:50:42 -0500 |
commit | 6fe5186f0c7c18a8beb6d96c21e2390df7a12375 (patch) | |
tree | 2a8a65b4a48252c2fa9701653e4ef229cd01089a /mm/zsmalloc.c | |
parent | 6f0b22760b7d8317569252cc7c36cbed22ebe401 (diff) |
zsmalloc: reduce size_class memory usage
Each `struct size_class' contains `struct zs_size_stat': an array of
NR_ZS_STAT_TYPE `unsigned long'. For zsmalloc built with no
CONFIG_ZSMALLOC_STAT this results in a waste of `2 * sizeof(unsigned
long)' per-class.
The patch removes unneeded `struct zs_size_stat' members by redefining
NR_ZS_STAT_TYPE (max stat idx in array).
Since both NR_ZS_STAT_TYPE and zs_stat_type are compile time constants,
GCC can eliminate zs_stat_inc()/zs_stat_dec() calls that use zs_stat_type
larger than NR_ZS_STAT_TYPE: CLASS_ALMOST_EMPTY and CLASS_ALMOST_FULL at
the moment.
./scripts/bloat-o-meter mm/zsmalloc.o.old mm/zsmalloc.o.new
add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-39 (-39)
function old new delta
fix_fullness_group 97 94 -3
insert_zspage 100 86 -14
remove_zspage 141 119 -22
To summarize:
a) each class now uses less memory
b) we avoid a number of dec/inc stats (a minor optimization,
but still).
The gain will increase once we introduce additional stats.
A simple IO test.
iozone -t 4 -R -r 32K -s 60M -I +Z
patched base
" Initial write " 4145599.06 4127509.75
" Rewrite " 4146225.94 4223618.50
" Read " 17157606.00 17211329.50
" Re-read " 17380428.00 17267650.50
" Reverse Read " 16742768.00 16162732.75
" Stride read " 16586245.75 16073934.25
" Random read " 16349587.50 15799401.75
" Mixed workload " 10344230.62 9775551.50
" Random write " 4277700.62 4260019.69
" Pwrite " 4302049.12 4313703.88
" Pread " 6164463.16 6126536.72
" Fwrite " 7131195.00 6952586.00
" Fread " 12682602.25 12619207.50
Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Cc: 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/zsmalloc.c')
-rw-r--r-- | mm/zsmalloc.c | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c index a8ff24a29693..2858b20dce76 100644 --- a/mm/zsmalloc.c +++ b/mm/zsmalloc.c | |||
@@ -167,9 +167,14 @@ enum zs_stat_type { | |||
167 | OBJ_USED, | 167 | OBJ_USED, |
168 | CLASS_ALMOST_FULL, | 168 | CLASS_ALMOST_FULL, |
169 | CLASS_ALMOST_EMPTY, | 169 | CLASS_ALMOST_EMPTY, |
170 | NR_ZS_STAT_TYPE, | ||
171 | }; | 170 | }; |
172 | 171 | ||
172 | #ifdef CONFIG_ZSMALLOC_STAT | ||
173 | #define NR_ZS_STAT_TYPE (CLASS_ALMOST_EMPTY + 1) | ||
174 | #else | ||
175 | #define NR_ZS_STAT_TYPE (OBJ_USED + 1) | ||
176 | #endif | ||
177 | |||
173 | struct zs_size_stat { | 178 | struct zs_size_stat { |
174 | unsigned long objs[NR_ZS_STAT_TYPE]; | 179 | unsigned long objs[NR_ZS_STAT_TYPE]; |
175 | }; | 180 | }; |
@@ -448,19 +453,23 @@ static int get_size_class_index(int size) | |||
448 | static inline void zs_stat_inc(struct size_class *class, | 453 | static inline void zs_stat_inc(struct size_class *class, |
449 | enum zs_stat_type type, unsigned long cnt) | 454 | enum zs_stat_type type, unsigned long cnt) |
450 | { | 455 | { |
451 | class->stats.objs[type] += cnt; | 456 | if (type < NR_ZS_STAT_TYPE) |
457 | class->stats.objs[type] += cnt; | ||
452 | } | 458 | } |
453 | 459 | ||
454 | static inline void zs_stat_dec(struct size_class *class, | 460 | static inline void zs_stat_dec(struct size_class *class, |
455 | enum zs_stat_type type, unsigned long cnt) | 461 | enum zs_stat_type type, unsigned long cnt) |
456 | { | 462 | { |
457 | class->stats.objs[type] -= cnt; | 463 | if (type < NR_ZS_STAT_TYPE) |
464 | class->stats.objs[type] -= cnt; | ||
458 | } | 465 | } |
459 | 466 | ||
460 | static inline unsigned long zs_stat_get(struct size_class *class, | 467 | static inline unsigned long zs_stat_get(struct size_class *class, |
461 | enum zs_stat_type type) | 468 | enum zs_stat_type type) |
462 | { | 469 | { |
463 | return class->stats.objs[type]; | 470 | if (type < NR_ZS_STAT_TYPE) |
471 | return class->stats.objs[type]; | ||
472 | return 0; | ||
464 | } | 473 | } |
465 | 474 | ||
466 | #ifdef CONFIG_ZSMALLOC_STAT | 475 | #ifdef CONFIG_ZSMALLOC_STAT |