Linux的线程创建限制
来源:互联网 发布:淘宝发v任务要钱吗 编辑:程序博客网 时间:2024/06/09 18:50
导言:现网有个版本上线一段时间后,通过SSH重新登陆时显示
Cannot allocate memory
错误,结果只能通过重启机器来恢复服务。通过分析发现是新的版本引入一个bug,某个进程会不停地创建新的线程,那么问题是Linux下一个进程可以创建多少个线程,从而会导致这个错误出现。
1 原因分析
问题重现,通过一个测试程序,验证错误是否会重现。
#include <iostream>#include <pthread.h>#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>using namespace std;void* thr_func (void*){ for(;;) sleep(500); return 0;}void max_thread_test (){ const int MAX = 4194304; //const int MAX = 10; int i = 0; for (; i < MAX; ++i) { int ret = 0; pthread_attr_t attr; pthread_attr_init(&attr); // detached ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if (ret) { perror("pthread_attr_setdetachstate err"); exit(1); } size_t stacksize = 0; ret = pthread_attr_getstacksize(&attr, &stacksize); if (ret) { perror("pthread_attr_getstacksize err"); exit(1); } else { static bool once = true; if (once) { std::cout << "default thread stacksize: " << stacksize << std::endl; once = false; } } // thread stacksize stacksize = 16384;// 16KB ret = pthread_attr_setstacksize(&attr, stacksize); if (ret) { perror("pthread_attr_setstacksize err"); exit(1); } else { static bool once = true; if (once) { std::cout << "change thread stacksize to : " << stacksize << std::endl; once = false; } } if (!(i % (MAX / 10000))) std::cerr << "..." << i; pthread_t thread; ret = pthread_create(&thread, &attr, thr_func, NULL); if (ret) { std::cerr << "\nthreads created " << i << std::endl ; perror("pthread_create"); exit(1); } } std::cerr << "threads created " << i - 1 << std::endl ; std::cout << "exit (succes)" << std::endl;}int main(){ max_thread_test(); for(;;) sleep(5000); std::cout << "end" << std::endl; return 0;}/* 在Mac上使用LLVM/Clang编译得到如下结果:$./test_max_thread default thread stacksize: 524288change thread stacksize to : 16384...0...419...838...1257...1676threads created 2047pthread_create: Cannot allocate memory* */
通过max-thread-per-process-in-linux和Maximum number of threads per process in Linux?可以得知,除了内存大小限制外,还有很多内核参数的限制,但理论上一个进程可以创建的最大线程数量为:
number of threads = total virtual memory / stack size
因此,32位系统由于进程的虚拟地址空间为4G,可以创建的线程数量为3G/8M=384个线程,而64位系统的进程可以创建的线程数量为128T/8M=16777216个线程(千万级)。当然在实际使用中一般不会创建这么多线程,因为线程间的切换会占用2000+的CPU时钟周期,可能导致CPU过高。一般会根据CPU核数启用相应的线程数,尽量减少不必要的线程切换。
通过修改下面的参数,可以尽可能地创建更多的线程。
echo 1 > /proc/sys/vm/overcommit_memory echo 1000000 > /proc/sys/kernel/threads-maxecho 10000000 > /proc/sys/vm/max_map_countecho "4194304" > /proc/sys/kernel/pid_max
max_map_count的补充说明:在Linux上测试,创建一次线程操作会调用一次mmap,但是会映射两个地址段(/proc/pid/maps有两行,一个4KB,一个8MB),map_count会累积两次,所以一个进程要满足:创建线程数*2 + 其他的映射地址段数量 < max_map_count
2 Refer
man 5 proc
理解Linux的memory overcommit
Infographics: Operation Costs in CPU Clock Cycles
http://www.kegel.com/c10k.html#limits.threads
https://www.akkadia.org/drepper/glibcthreads.html
https://www.akkadia.org/drepper/nptl-design.pdf
NPTL caps maximum threads at 65528?
- Linux的线程创建限制
- Linux线程的创建
- Linux中突破线程数的限制
- 修改linux线程限制
- Linux下线程的创建
- Linux下线程的创建
- Linux下线程的创建
- linux下线程的创建
- linux内核线程的创建
- 浅析Linux线程的创建
- 浅析Linux线程的创建
- linux下线程的创建
- linux下线程的创建
- linux 下线程的创建
- Linux线程(1): 线程的创建
- Linux最大线程数限制
- LINUX如何限制单个用户的线程数
- Linux下的通用线程池创建
- VUe+webpack构建单页router应用(一)
- 并查集问题
- 小试Python——爬虫抓取大众点评上的数据
- k8s petset 特性
- automake——automake简易教程
- Linux的线程创建限制
- MVC框架
- Linux NAT组建虚拟机局域网并且局域网内各虚拟机能上网
- Solr查询参数sort(排序)
- golang判断是否本机ip
- UIView 的动画效果
- hdu1207(递推)
- python爬虫基础-http协议
- ubuntu安装jdk7和jdk8