sys.kernel.threads-max默认值
背景
物理机时代,业务根据/proc/sys/kernel/threads-max
设置线程池大小。容器(特指docker)该值仍然获取的是物理机上的信息,而容器规格一般比物理机小,再根据这个值获取信息设置容器内线程数就不准确了。物理机上这个值受哪些资源影响,因此有了这篇文章。
梳理
内核版本4.18 线程数限制为[20,0x3fffffff]
代码中设置threads的计算公式
threads = div64_u64((u64) totalram_pages * (u64) PAGE_SIZE, (u64) THREAD_SIZE * 8UL);
当threads < min
时, 取MIN_THREADS
; 当threads > max
时, 取MAX_THREADS
; 否则,取threads值。其中 max_threads_suggested
值传入的就是MAX_THREADS
将totalram_pages*PAGE_SIZE ≈ totalram
,代入公式
threads = div64_u64((u64) totalram_pages * (u64) PAGE_SIZE, (u64) THREAD_SIZE * 8UL);
得到
threads ≈ div64_u64(totalram, THREAD_SIZE*8)
上面totalram_pages*PAGE_SIZE ≈ totalram
说近似相等,是因为物理内存并不是全归内核管理,还有一部分内存是处于内核代码段/dtb(device tree blob)及保留内存+系统共用内存部分
根据configs/kernel-4.18.0-x86_64.config得知 # CONFIG_KASAN is not set
所以KASAN_STACK_ORDER = 0
代入计算,得到
threads ≈ div64_u64(totalram,(PAGE_SIZE << THREAD_SIZE_ORDER)*8)
=>
threads ≈ div64_u64(totalram,(PAGE_SIZE << 2)*8)
代入计算
threads ≈ div64_u64(totalram, 16KB*8)
验证
预估值 free -k | grep Mem | awk '{printf("%d\n", $2/128)}'
或 cat /proc/meminfo |grep MemTotal | awk '{printf("%d\n", $2/128)}'
实际值 cat /proc/sys/kernel/threads-max
结论
max-threads 约为内存大小(单位KB) ➗ 128