mm, slab: Make kmalloc_info[] contain all types of names
Subsystems (2)
v3 cover mm, slab: Make kmalloc_info[] contain all types of names
Changes in v3
--
1. restore __initconst (patch 1/4)
2. rename patch 3/4
3. add more clarification for patch 4/4
Changes in v2
--
1. remove __initconst (patch 1/5)
2. squash patch 2/5
3. add ack tag from Vlastimil Babka
There are three types of kmalloc, KMALLOC_NORMAL, KMALLOC_RECLAIM and KMALLOC_DMA.
The name of KMALLOC_NORMAL is contained in kmalloc_info[].name, but the names of KMALLOC_RECLAIM and KMALLOC_DMA are dynamically generated by kmalloc_cache_name().
Patch1 predefines the names of all types of kmalloc to save the time spent dynamically generating names.
The other 4 patches did some cleanup work.
These changes make sense, and the time spent by new_kmalloc_cache() has been reduced by approximately 36.3%.
Time spent by
new_kmalloc_cache()
5.3-rc7 66264
5.3-rc7+patch 42188
Pengfei Li (4):
mm, slab: Make kmalloc_info[] contain all types of names mm, slab: Remove unused kmalloc_size()
mm, slab_common: use enum kmalloc_cache_type to iterate over kmalloc
caches
mm, slab_common: Make the loop for initializing KMALLOC_DMA start from
1
include/linux/slab.h | 20 --------- mm/slab.c | 7 +-- mm/slab.h | 2 +- mm/slab_common.c | 101 +++++++++++++++++++++++-------------------- 4 files changed, 59 insertions(+), 71 deletions(-)
Signature · 1 line
2.21.0
PATCH v3 1/4 mm, slab: Make kmalloc_info[] contain all types of names
There are three types of kmalloc, KMALLOC_NORMAL, KMALLOC_RECLAIM and KMALLOC_DMA.
The name of KMALLOC_NORMAL is contained in kmalloc_info[].name, but the names of KMALLOC_RECLAIM and KMALLOC_DMA are dynamically generated by kmalloc_cache_name().
This patch predefines the names of all types of kmalloc to save the time spent dynamically generating names.
Besides, remove the kmalloc_cache_name() that is no longer used.
--- mm/slab.c | 2 +- mm/slab.h | 2 +- mm/slab_common.c | 91 ++++++++++++++++++++++++++---------------------- 3 files changed, 51 insertions(+), 44 deletions(-)
mm/slab.c +1 -1
@@ -1247,7 +1247,7 @@ void __init kmem_cache_init(void)* structures first. Without this, further allocations will bug. */ kmalloc_caches[KMALLOC_NORMAL ][INDEX_NODE ] =create_kmalloc_cache ( - kmalloc_info[INDEX_NODE ].name, + kmalloc_info[INDEX_NODE ].name[KMALLOC_NORMAL ],kmalloc_size (INDEX_NODE ),ARCH_KMALLOC_FLAGS ,0 ,kmalloc_size (INDEX_NODE )); slab_state =PARTIAL_NODE ;
mm/slab.h +1 -1
@@ -76,7 +76,7 @@ extern struct kmem_cache *kmem_cache;/* A table of kmalloc cache names and sizes */ extern const struct kmalloc_info_struct { -const char *name; +const char *name[NR_KMALLOC_TYPES ];unsigned int size; } kmalloc_info[];
mm/slab_common.c +49 -42
122 lines not on this page · raw message
Signature · 1 line
2.21.0
PATCH v3 2/4 mm, slab: Remove unused kmalloc_size()
In reply to Pengfei LiThe size of kmalloc can be obtained from kmalloc_info[], so remove kmalloc_size() that will not be used anymore.
--- include/linux/slab.h | 20 -------------------- mm/slab.c | 5 +++-- mm/slab_common.c | 5 ++--- 3 files changed, 5 insertions(+), 25 deletions(-)
include/linux/slab.h +0 -20
@@ -557,26 +557,6 @@ static __always_inline void *kmalloc(size_t size, gfp_t flags)return __kmalloc (size, flags); } -/* -* Determine size used for the nth kmalloc cache. -* return size or 0 if a kmalloc cache for that -* size does not exist -*/ -static __always_inline unsigned int kmalloc_size(unsigned int n) -{ -#ifndef CONFIG_SLOB -if (n >2 ) -return 1U << n; - -if (n ==1 &&KMALLOC_MIN_SIZE <=32 ) -return 96 ; - -if (n ==2 &&KMALLOC_MIN_SIZE <=64 ) -return 192 ; -#endif -return 0 ; -} - static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node) {#ifndef CONFIG_SLOB
mm/slab.c +3 -2
@@ -1248,8 +1248,9 @@ void __init kmem_cache_init(void)*/ kmalloc_caches[KMALLOC_NORMAL ][INDEX_NODE ] =create_kmalloc_cache ( kmalloc_info[INDEX_NODE ].name[KMALLOC_NORMAL ], -kmalloc_size (INDEX_NODE ),ARCH_KMALLOC_FLAGS , -0 ,kmalloc_size (INDEX_NODE )); + kmalloc_info[INDEX_NODE ].size, +ARCH_KMALLOC_FLAGS ,0 , + kmalloc_info[INDEX_NODE ].size); slab_state =PARTIAL_NODE ;setup_kmalloc_cache_index_table ();
mm/slab_common.c +2 -3
@@ -1239,11 +1239,10 @@ void __init create_kmalloc_caches(slab_flags_t flags)struct kmem_cache *s = kmalloc_caches[KMALLOC_NORMAL ][i];if (s) { -unsigned int size =kmalloc_size (i); - kmalloc_caches[KMALLOC_DMA ][i] =create_kmalloc_cache ( kmalloc_info[i].name[KMALLOC_DMA ], - size,SLAB_CACHE_DMA | flags,0 ,0 ); + kmalloc_info[i].size, +SLAB_CACHE_DMA | flags,0 ,0 ); } }#endif
Signature · 1 line
2.21.0
PATCH v3 3/4 mm, slab_common: use enum kmalloc_cache_type to iterate over kmalloc caches
In reply to Pengfei LiThe type of local variable *type* of new_kmalloc_cache() should be enum kmalloc_cache_type instead of int, so correct it.
--- mm/slab_common.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
mm/slab_common.c +3 -2
@@ -1192,7 +1192,7 @@ void __init setup_kmalloc_cache_index_table(void) }static void __init -new_kmalloc_cache (int idx,int type,slab_flags_t flags) +new_kmalloc_cache (int idx,enum kmalloc_cache_type type,slab_flags_t flags) {if (type ==KMALLOC_RECLAIM ) flags |=SLAB_RECLAIM_ACCOUNT ;
@@ -1210,7 +1210,8 @@ new_kmalloc_cache(int idx, int type, slab_flags_t flags)*/ void __init create_kmalloc_caches (slab_flags_t flags) { -int i, type; +int i; +enum kmalloc_cache_type type;for (type =KMALLOC_NORMAL ; type <=KMALLOC_RECLAIM ; type++) {for (i =KMALLOC_SHIFT_LOW ; i <=KMALLOC_SHIFT_HIGH ; i++) {
Signature · 1 line
2.21.0
PATCH v3 4/4 mm, slab_common: Make the loop for initializing KMALLOC_DMA start from 1
In reply to Pengfei LiKMALLOC_DMA will be initialized only if KMALLOC_NORMAL with the same index exists.
And kmalloc_caches[KMALLOC_NORMAL][0] is always NULL.
Therefore, the loop that initializes KMALLOC_DMA should start at 1 instead of 0, which will reduce 1 meaningless attempt.
--- mm/slab_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
mm/slab_common.c +1 -1
@@ -1236,7 +1236,7 @@ void __init create_kmalloc_caches(slab_flags_t flags) slab_state =UP ;#ifdef CONFIG_ZONE_DMA -for (i =0 ; i <=KMALLOC_SHIFT_HIGH ; i++) { +for (i =1 ; i <=KMALLOC_SHIFT_HIGH ; i++) {struct kmem_cache *s = kmalloc_caches[KMALLOC_NORMAL ][i];if (s) {
Signature · 1 line
2.21.0
Re: [PATCH v3 4/4] mm, slab_common: Make the loop for initializing KMALLOC_DMA start from 1
Quoted 7 lines · Pengfei Li
KMALLOC_DMAwill be initialized only ifKMALLOC_NORMALwith the same index exists.And kmalloc_caches[KMALLOC_NORMAL][0] is always NULL.
Therefore, the loop that initializes
KMALLOC_DMAshould start at 1 instead of 0, which will reduce 1 meaningless attempt.
IMHO the saving of one iteration isn't worth making the code more subtle. KMALLOC_SHIFT_LOW would be nice, but that would skip 1 + 2 which are special.
Since you're doing these cleanups, have you considered reordering kmalloc_info, size_index, kmalloc_index() etc so that sizes 96 and 192 are ordered naturally between 64, 128 and 256? That should remove various special casing such as in create_kmalloc_caches(). I can't guarantee it will be possible without breaking e.g. constant folding optimizations etc., but seems to me it should be feasible. (There are definitely more places to change than those I listed.)
Quoted 19 lines
Signed-off-by Pengfei Li <[email protected]>--- mm/slab_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)mm/slab_common.c +1
-1@@ -1236,7 +1236,7 @@ void __init create_kmalloc_caches(slab_flags_t flags) slab_state =UP ;#ifdef CONFIG_ZONE_DMA -for (i =0 ; i <=KMALLOC_SHIFT_HIGH ; i++) { +for (i =1 ; i <=KMALLOC_SHIFT_HIGH ; i++) {struct kmem_cache *s = kmalloc_caches[KMALLOC_NORMAL ][i];if (s) {
Re: [PATCH v3 4/4] mm, slab_common: Make the loop for initializing KMALLOC_DMA start from 1
Quoted 5 lines · Vlastimil Babka
Quoted 3 lines · Pengfei Li
KMALLOC_DMAwill be initialized only ifKMALLOC_NORMALwith the same index exists.
Quoted 9 lines
Quoted 4 lines
And kmalloc_caches[KMALLOC_NORMAL][0] is always NULL.
Therefore, the loop that initializes
KMALLOC_DMAshould start at 1 instead of 0, which will reduce 1 meaningless attempt.IMHO the saving of one iteration isn't worth making the code more subtle.
KMALLOC_SHIFT_LOWwould be nice, but that would skip 1 + 2 which are special.
Yes, I agree with you.
This really makes the code more subtle.
Quoted 8 lines
Since you're doing these cleanups, have you considered reordering
kmalloc_info,size_index,kmalloc_index()etc so that sizes 96 and 192 are ordered naturally between 64, 128 and 256? That should remove various special casing such as increate_kmalloc_caches(). I can't guarantee it will be possible without breaking e.g. constant folding optimizations etc., but seems to me it should be feasible. (There are definitely more places to change than those I listed.)
In the past two days, I am working on what you suggested.
So far, I have completed the coding work, but I need some time to make sure there are no bugs and verify the impact on performance.
I will send v4 soon.
Thank you for your review and suggestions.
--
Pengfei
Quoted 20 lines
Quoted 19 lines
Signed-off-by Pengfei Li <[email protected]>--- mm/slab_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)mm/slab_common.c +1
-1@@ -1236,7 +1236,7 @@ void __init create_kmalloc_caches(slab_flags_t flags) slab_state =UP ;#ifdef CONFIG_ZONE_DMA -for (i =0 ; i <=KMALLOC_SHIFT_HIGH ; i++) { +for (i =1 ; i <=KMALLOC_SHIFT_HIGH ; i++) {struct kmem_cache *s = kmalloc_caches[KMALLOC_NORMAL ][i];if (s) {
Re: [PATCH v3 4/4] mm, slab_common: Make the loop for initializing KMALLOC_DMA start from 1
Quoted 1 line · Pengfei Li
In the past two days, I am working on what you suggested.
Great!
Quoted 2 lines
So far, I have completed the coding work, but I need some time to make sure there are no bugs and verify the impact on performance.
It would probably be hard to measure with sufficient confidence in terms of runtime performance, but you could use e.g. ./scripts/bloat-o-meter to look for unexpected code increase due to compile-time optimizations becoming runtime.