Skip to content

Commit c4a6fce

Browse files
soleenakpm00
authored andcommitted
vmstat: kernel stack usage histogram
As part of the dynamic kernel stack project, we need to know the amount of data that can be saved by reducing the default kernel stack size [1]. Provide a kernel stack usage histogram to aid in optimizing kernel stack sizes and minimizing memory waste in large-scale environments. The histogram divides stack usage into power-of-two buckets and reports the results in /proc/vmstat. This information is especially valuable in environments with millions of machines, where even small optimizations can have a significant impact. The histogram data is presented in /proc/vmstat with entries like "kstack_1k", "kstack_2k", and so on, indicating the number of threads that exited with stack usage falling within each respective bucket. Example outputs: Intel: $ grep kstack /proc/vmstat kstack_1k 3 kstack_2k 188 kstack_4k 11391 kstack_8k 243 kstack_16k 0 ARM with 64K page_size: $ grep kstack /proc/vmstat kstack_1k 1 kstack_2k 340 kstack_4k 25212 kstack_8k 1659 kstack_16k 0 kstack_32k 0 kstack_64k 0 Note: once the dynamic kernel stack is implemented it will depend on the implementation the usability of this feature: On hardware that supports faults on kernel stacks, we will have other metrics that show the total number of pages allocated for stacks. On hardware where faults are not supported, we will most likely have some optimization where only some threads are extended, and for those, these metrics will still be very useful. [1] https://lwn.net/Articles/974367 Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Pasha Tatashin <[email protected]> Reviewed-by: Kent Overstreet <[email protected]> Acked-by: Shakeel Butt <[email protected]> Cc: Domenico Cerasuolo <[email protected]> Cc: Li Zhijian <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: Nhat Pham <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Suren Baghdasaryan <[email protected]> Cc: Vlastimil Babka <[email protected]> Cc: Zi Yan <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 9db298a commit c4a6fce

File tree

3 files changed

+86
-0
lines changed

3 files changed

+86
-0
lines changed

include/linux/vm_event_item.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,30 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
155155
VMA_LOCK_RETRY,
156156
VMA_LOCK_MISS,
157157
#endif
158+
#ifdef CONFIG_DEBUG_STACK_USAGE
159+
KSTACK_1K,
160+
#if THREAD_SIZE > 1024
161+
KSTACK_2K,
162+
#endif
163+
#if THREAD_SIZE > 2048
164+
KSTACK_4K,
165+
#endif
166+
#if THREAD_SIZE > 4096
167+
KSTACK_8K,
168+
#endif
169+
#if THREAD_SIZE > 8192
170+
KSTACK_16K,
171+
#endif
172+
#if THREAD_SIZE > 16384
173+
KSTACK_32K,
174+
#endif
175+
#if THREAD_SIZE > 32768
176+
KSTACK_64K,
177+
#endif
178+
#if THREAD_SIZE > 65536
179+
KSTACK_REST,
180+
#endif
181+
#endif /* CONFIG_DEBUG_STACK_USAGE */
158182
NR_VM_EVENT_ITEMS
159183
};
160184

kernel/exit.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -778,13 +778,51 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
778778
}
779779

780780
#ifdef CONFIG_DEBUG_STACK_USAGE
781+
/* Count the maximum pages reached in kernel stacks */
782+
static inline void kstack_histogram(unsigned long used_stack)
783+
{
784+
#ifdef CONFIG_VM_EVENT_COUNTERS
785+
if (used_stack <= 1024)
786+
count_vm_event(KSTACK_1K);
787+
#if THREAD_SIZE > 1024
788+
else if (used_stack <= 2048)
789+
count_vm_event(KSTACK_2K);
790+
#endif
791+
#if THREAD_SIZE > 2048
792+
else if (used_stack <= 4096)
793+
count_vm_event(KSTACK_4K);
794+
#endif
795+
#if THREAD_SIZE > 4096
796+
else if (used_stack <= 8192)
797+
count_vm_event(KSTACK_8K);
798+
#endif
799+
#if THREAD_SIZE > 8192
800+
else if (used_stack <= 16384)
801+
count_vm_event(KSTACK_16K);
802+
#endif
803+
#if THREAD_SIZE > 16384
804+
else if (used_stack <= 32768)
805+
count_vm_event(KSTACK_32K);
806+
#endif
807+
#if THREAD_SIZE > 32768
808+
else if (used_stack <= 65536)
809+
count_vm_event(KSTACK_64K);
810+
#endif
811+
#if THREAD_SIZE > 65536
812+
else
813+
count_vm_event(KSTACK_REST);
814+
#endif
815+
#endif /* CONFIG_VM_EVENT_COUNTERS */
816+
}
817+
781818
static void check_stack_usage(void)
782819
{
783820
static DEFINE_SPINLOCK(low_water_lock);
784821
static int lowest_to_date = THREAD_SIZE;
785822
unsigned long free;
786823

787824
free = stack_not_used(current);
825+
kstack_histogram(THREAD_SIZE - free);
788826

789827
if (free >= lowest_to_date)
790828
return;

mm/vmstat.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1436,6 +1436,30 @@ const char * const vmstat_text[] = {
14361436
"vma_lock_retry",
14371437
"vma_lock_miss",
14381438
#endif
1439+
#ifdef CONFIG_DEBUG_STACK_USAGE
1440+
"kstack_1k",
1441+
#if THREAD_SIZE > 1024
1442+
"kstack_2k",
1443+
#endif
1444+
#if THREAD_SIZE > 2048
1445+
"kstack_4k",
1446+
#endif
1447+
#if THREAD_SIZE > 4096
1448+
"kstack_8k",
1449+
#endif
1450+
#if THREAD_SIZE > 8192
1451+
"kstack_16k",
1452+
#endif
1453+
#if THREAD_SIZE > 16384
1454+
"kstack_32k",
1455+
#endif
1456+
#if THREAD_SIZE > 32768
1457+
"kstack_64k",
1458+
#endif
1459+
#if THREAD_SIZE > 65536
1460+
"kstack_rest",
1461+
#endif
1462+
#endif
14391463
#endif /* CONFIG_VM_EVENT_COUNTERS || CONFIG_MEMCG */
14401464
};
14411465
#endif /* CONFIG_PROC_FS || CONFIG_SYSFS || CONFIG_NUMA || CONFIG_MEMCG */

0 commit comments

Comments
 (0)