Show slab memory usage on OOM and SysRq-M
Subsystems (5)
PATCH 1/1 Show slab memory usage on OOM and SysRq-M
The out_of_memory() function and SysRq-M handler call show_mem() to show the current memory usage state.
This is also helpful to see which slabs are the largest in the system.
---
drivers/char/sysrq.c +1 -0
@@ -234,6 +234,7 @@ static struct sysrq_key_op sysrq_showstastatic void sysrq_handle_showmem (int key,struct tty_struct *tty) {show_mem (); +show_slabs (); }static struct sysrq_key_op sysrq_showmem_op = { .handler = sysrq_handle_showmem,
include/linux/mm.h +0 -0
include/linux/slab.h +6 -0
@@ -170,6 +170,12 @@ static inline void *kzalloc(size_t size, }#endif +#ifdef CONFIG_SLAB +extern void show_slabs (void ); +#else +#define show_slabs (void) do { } while (0) +#endif +#ifndef CONFIG_NUMA static inline void *kmalloc_node (size_t size,gfp_t flags,int node) {
mm/oom_kill.c +1 -0
@@ -409,6 +409,7 @@ void out_of_memory(struct zonelist *zone current->comm, gfp_mask, order, current->oomkilladj);dump_stack ();show_mem (); +show_slabs (); }cpuset_lock ();
mm/slab.c +74 -0
103 lines not on this page · raw message
Hi,
Quoted 5 lines · Pavel Emelianov
The
out_of_memory()function and SysRq-M handler callshow_mem()to show the current memory usage state.This is also helpful to see which slabs are the largest in the system.
Makes sense.
mm/slab.c static inline void init_lock_keys(void) · line 752
Quoted 9 lines · Pavel Emelianov
mm/slab.c +1
-0@@ -749,6 +749,7 @@ static inline void init_lock_keys(void)* 2. Protect sanity of cpu_online_map against cpu hotplug events */ static DEFINE_MUTEX (cache_chain_mutex); +static DEFINE_SPINLOCK (cache_chain_lock);
So, now we have two locks protecting cache_chain? Please explain why you can't use the mutex.
Quoted 17 lines
mm/slab.c +17
-0+static unsigned long get_cache_size (struct kmem_cache *cachep) +{ +unsigned long slabs; +struct kmem_list3 *l3; +struct list_head *lh; +int node; + + slabs =0 ; + +for_each_online_node (node) { + l3 = cachep->nodelists[node]; +if (l3 ==NULL ) +continue ; + +spin_lock (&l3->list_lock); +list_for_each (lh, &l3->slabs_full) + slabs++;
mm/slab.c const struct seq_operations slabstats_op · line 4581
Quoted 10 lines
mm/slab.c +10
-0+list_for_each (lh, &l3->slabs_partial) + slabs++; +list_for_each (lh, &l3->slabs_free) + slabs++; +spin_unlock (&l3->list_lock); + } + +return slabs * ((PAGE_SIZE << cachep->gfporder) + + (OFF_SLAB (cachep) ? cachep->slabp_cache->buffer_size :0 )); +}
Considering you're doing this at out_of_memory() time, wouldn't it make more sense to add a ->nr_pages to struct kmem_cache and do the tracking in kmem_getpages/kmem_freepages?
I would also drop the OFF_SLAB bits because it really doesn't matter that much for your purposes. Besides, you're already per-node and per-CPU caches here which attribute to much more memory on NUMA setups for example.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 10 lines · Pekka Enberg
Hi,
Quoted 5 lines · Pavel Emelianov
The
out_of_memory()function and SysRq-M handler callshow_mem()to show the current memory usage state.This is also helpful to see which slabs are the largest in the system.
Makes sense.
Thanks! :)
Quoted 5 lines · Pavel Emelianov
Quoted 4 lines
mm/slab.c +0
-0
Quoted 8 lines
mm/slab.c static inline void init_lock_keys(void) · line 752
Quoted 5 lines
mm/slab.c +1
-0@@ -749,6 +749,7 @@ static inline void init_lock_keys(void)* 2. Protect sanity of cpu_online_map against cpu hotplug events */ static DEFINE_MUTEX (cache_chain_mutex); +static DEFINE_SPINLOCK (cache_chain_lock);So, now we have two locks protecting
cache_chain? Please explain why you can't use the mutex.
Because OOM can actually happen with this mutex locked. For example kmem_cache_create() locks it and calls kmalloc(), or write to /proc/slabinfo also locks it and calls do_tune_cpu_caches(). This is very rare case and the deadlock is VERY unlikely to happen, but it will be very disappointing if it happens.
Moreover, I put the call to show_slabs() into sysrq handler, so it may be called from atomic context.
Making mutex_trylock() is possible, but we risk of loosing this info in case OOM happens while the mutex is locked for cache shrinking (see cache_reap() for example)...
So we have a choice - either we have an additional lock on a slow and rare paths and show this info for sure, or we do not have a lock, but have a risk of loosing this info.
Quoted 24 lines
Quoted 24 lines
mm/slab.c +24
-0+static unsigned long get_cache_size (struct kmem_cache *cachep) +{ +unsigned long slabs; +struct kmem_list3 *l3; +struct list_head *lh; +int node; + + slabs =0 ; + +for_each_online_node (node) { + l3 = cachep->nodelists[node]; +if (l3 ==NULL ) +continue ; + +spin_lock (&l3->list_lock); +list_for_each (lh, &l3->slabs_full) + slabs++; +list_for_each (lh, &l3->slabs_partial) + slabs++; +list_for_each (lh, &l3->slabs_free) + slabs++; +spin_unlock (&l3->list_lock); + } +
Quoted 8 lines
Quoted 4 lines
mm/slab.c +2
-0+ return slabs * ((PAGE_SIZE << cachep->gfporder) + + (OFF_SLAB(cachep) ? cachep->slabp_cache->buffer_size :0));
+}Considering you're doing this at
out_of_memory()time, wouldn't it make more sense to add a ->nr_pages to structkmem_cacheand do the tracking in kmem_getpages/kmem_freepages?
Sounds good.
Quoted 4 lines
I would also drop the
OFF_SLABbits because it really doesn't matter that much for your purposes. Besides, you're already per-node and per-CPU caches here which attribute to much more memory on NUMA setups for example.
This gives us a more precise information :) The precision is less than 1% so if nobody likes/needs it, this may be dropped.
Pavel.
Hi Pavel,
Quoted 2 lines · At some point in time, I wrote:
Quoted 2 lines
So, now we have two locks protecting
cache_chain? Please explain why you can't use the mutex.
Quoted 9 lines · Pavel Emelianov
Because OOM can actually happen with this mutex locked. For example
kmem_cache_create()locks it and callskmalloc(), or write to/proc/slabinfoalso locks it and callsdo_tune_cpu_caches(). This is very rare case and the deadlock is VERY unlikely to happen, but it will be very disappointing if it happens.Moreover, I put the call to
show_slabs()into sysrq handler, so it may be called from atomic context.
Quoted 7 lines
Making
mutex_trylock()is possible, but we risk of loosing this info in case OOM happens while the mutex is locked for cache shrinking (seecache_reap()for example)...So we have a choice - either we have an additional lock on a slow and rare paths and show this info for sure, or we do not have a lock, but have a risk of loosing this info.
I don't worry about performance as much I do about maintenance. Do you know if mutex_trylock() is a problem in practice? Could we perhaps fix the worst offenders who are holding cache_chain_mutex for a long time?
In any case, if we do end up adding the lock, please add a BIG FAT COMMENT explaining why we have it.
Quoted 4 lines · At some point in time, I wrote:
Quoted 4 lines
I would also drop the
OFF_SLABbits because it really doesn't matter that much for your purposes. Besides, you're already per-node and per-CPU caches here which attribute to much more memory on NUMA setups for example.
Quoted 2 lines · Pavel Emelianov
This gives us a more precise information :) The precision is less than 1% so if nobody likes/needs it, this may be dropped.
My point is that the "precision" is useless here. We probably waste more memory in the caches which are not accounted here. So I'd just drop it.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 20 lines · Pekka J Enberg
Hi Pavel,
Quoted 2 lines · At some point in time, I wrote:
Quoted 2 lines
So, now we have two locks protecting
cache_chain? Please explain why you can't use the mutex.Quoted 13 lines · Pavel Emelianov
Because OOM can actually happen with this mutex locked. For example
kmem_cache_create()locks it and callskmalloc(), or write to/proc/slabinfoalso locks it and callsdo_tune_cpu_caches(). This is very rare case and the deadlock is VERY unlikely to happen, but it will be very disappointing if it happens.Moreover, I put the call to
show_slabs()into sysrq handler, so it may be called from atomic context.Making
mutex_trylock()is possible, but we risk of loosing this info in case OOM happens while the mutex is locked for cache shrinking (seecache_reap()for example)...
Quoted 6 lines
Quoted 3 lines
So we have a choice - either we have an additional lock on a slow and rare paths and show this info for sure, or we do not have a lock, but have a risk of loosing this info.
I don't worry about performance as much I do about maintenance. Do you know if
mutex_trylock()is a problem in practice? Could we perhaps fix
No, this mutex is unlocked most of the time, but I have already been in the situations when the information that might not get on the screen did not actually get there in the most inappropriate moment :)
Quoted 4 lines
the worst offenders who are holding
cache_chain_mutexfor a long time?In any case, if we do end up adding the lock, please add a BIG FAT COMMENT explaining why we have it.
OK. I will keep this lock unless someone have a forcible argument for not doing this.
Quoted 6 lines
Quoted 4 lines · At some point in time, I wrote:
Quoted 4 lines
I would also drop the
OFF_SLABbits because it really doesn't matter that much for your purposes. Besides, you're already per-node and per-CPU caches here which attribute to much more memory on NUMA setups for example.
Quoted 6 lines
Quoted 2 lines · Pavel Emelianov
This gives us a more precise information :) The precision is less than 1% so if nobody likes/needs it, this may be dropped.
My point is that the "precision" is useless here. We probably waste more memory in the caches which are not accounted here. So I'd just drop it.
OK. I will rework the patch according to your comments.
Pavel.
Quoted 26 lines · On Tue, 17 Apr 2007 16:22:48 +0300 "Pekka Enberg" <[email protected]>…
Hi,
Quoted 23 lines · Pavel Emelianov
mm/slab.c +23
-0+static unsigned long get_cache_size (struct kmem_cache *cachep) +{ +unsigned long slabs; +struct kmem_list3 *l3; +struct list_head *lh; +int node; + + slabs =0 ; + +for_each_online_node (node) { + l3 = cachep->nodelists[node]; +if (l3 ==NULL ) +continue ; + +spin_lock (&l3->list_lock); +list_for_each (lh, &l3->slabs_full) + slabs++; +list_for_each (lh, &l3->slabs_partial) + slabs++; +list_for_each (lh, &l3->slabs_free) + slabs++; +spin_unlock (&l3->list_lock); + }
Quoted 9 lines
mm/slab.c const struct seq_operations slabstats_op · line 4581
Quoted 4 lines
mm/slab.c +4
-0+ +return slabs * ((PAGE_SIZE << cachep->gfporder) + + (OFF_SLAB (cachep) ? cachep->slabp_cache->buffer_size :0 )); +}Considering you're doing this at
out_of_memory()time, wouldn't it make more sense to add a ->nr_pages to structkmem_cacheand do the tracking in kmem_getpages/kmem_freepages?
To avoid a deadlock ? yes...
This nr_pages should be in struct kmem_list3, not in struct kmem_cache, or else you defeat NUMA optimizations if touching a field in kmem_cache at kmem_getpages()/kmem_freepages() time.
for_each_online_node (node) {
l3 = cachep->nodelists[node];
if (l3)
slabs += l3->nr_pages; /* dont lock l3->list_lock */
}--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 3 lines · Eric Dumazet
This
nr_pagesshould be in structkmem_list3, not in structkmem_cache, or else you defeat NUMA optimizations if touching a field inkmem_cacheat kmem_getpages()/kmem_freepages() time.
We already touch ->flags, ->gfpflags, and ->gfporder in kmem_getpages(). Sorry for my ignorance, but how is this different?
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 8 lines · On Wed, 18 Apr 2007 09:17:19 +0300 (EEST) Pekka J Enberg…
Quoted 3 lines · Eric Dumazet
This
nr_pagesshould be in structkmem_list3, not in structkmem_cache, or else you defeat NUMA optimizations if touching a field inkmem_cacheat kmem_getpages()/kmem_freepages() time.We already touch ->flags, ->gfpflags, and ->gfporder in
kmem_getpages(). Sorry for my ignorance, but how is this different?
Those fields are read. Thats OK, because several CPUS might share all those without problem.
But modifying one field in kmem_cache would invalidate one cache line for all cpus that would have to reload it later.
This is what we call "false sharing" or cache line ping pongs
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>