下面的代码应该是100,000个线程:
/* compile with: gcc -lpthread -o thread-limit thread-limit.c */ /* originally from: http://www.volano.com/linuxnotes.html */ #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <pthread.h> #include <string.h> #define MAX_THREADS 100000 int i; void run(void) { sleep(60 * 60); } int main(int argc, char *argv[]) { int rc = 0; pthread_t thread[MAX_THREADS]; printf("Creating threads ...\n"); for (i = 0; i < MAX_THREADS && rc == 0; i++) { rc = pthread_create(&(thread[i]), NULL, (void *) &run, NULL); if (rc == 0) { pthread_detach(thread[i]); if ((i + 1) % 100 == 0) printf("%i threads so far ...\n", i + 1); } else { printf("Failed with return code %i creating thread %i (%s).\n", rc, i + 1, strerror(rc)); // can we allocate memory? char *block = NULL; block = malloc(65545); if(block == NULL) printf("Malloc failed too :( \n"); else printf("Malloc worked, hmmm\n"); } } sleep(60*60); // ctrl+c to exit; makes it easier to see mem use exit(0); }
这是在32位RAM的64位机器上运行的; Debian 5.0安装,所有股票。
运行这个吐出以下内容:
65500 threads so far ... Failed with return code 12 creating thread 65529 (Cannot allocate memory). Malloc worked, hmmm
我当然没有用尽公羊; 我甚至可以同时启动多个这样的程序,并且都启动它们的65k线程。
(请不要build议我不要尝试启动超过10万个线程,这是简单的应用程序testing,我现在的基于epoll的服务器总是有大概20万个连接, 各种文章都build议线程可能是更好的select。 – 谢谢 :) )
提及/proc/sys/vm/max_map_count
是正确的。 提高这个值可以打开更多的线程; 不确定涉及的确切公式,但1mil +值允许一些300k +线程。
(对于任何尝试使用100k +线程的人,请查看pthread_create的mmap问题……当内存用完时,使新线程真的很慢。
一个可能的问题是主程序中的局部变量thread
。 我认为pthread_t在你的64位机器上是8个字节(假设64位版本)。 这将是80万字节的堆栈。 512K的堆栈限制是我想的一个问题。 512K / 8 = 65536,这可疑地接近你创建的线程数量。 你可以尝试动态分配这个数组,而不是把它放在堆栈上。
这可能有助于将程序中的堆栈大小设置为最小(如果这样还不够):
/* compile with: gcc -lpthread -o thread-limit thread-limit.c */ /* originally from: http://www.volano.com/linuxnotes.html */ #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <pthread.h> #include <string.h> #define MAX_THREADS 100000 int i; void run(void) { sleep(60 * 60); } int main(int argc, char *argv[]) { int rc = 0; pthread_t thread[MAX_THREADS]; pthread_attr_t thread_attr; pthread_attr_init(&thread_attr); pthread_attr_setstacksize(&thread_attr, PTHREAD_STACK_MIN); printf("Creating threads ...\n"); for (i = 0; i < MAX_THREADS && rc == 0; i++) { rc = pthread_create(&(thread[i]), &thread_attr, (void *) &run, NULL); if (rc == 0) { pthread_detach(thread[i]); if ((i + 1) % 100 == 0) printf("%i threads so far ...\n", i + 1); } else { printf("Failed with return code %i creating thread %i (%s).\n", rc, i + 1, strerror(rc)); // can we allocate memory? char *block = NULL; block = malloc(65545); if(block == NULL) printf("Malloc failed too :( \n"); else printf("Malloc worked, hmmm\n"); } } sleep(60*60); // ctrl+c to exit; makes it easier to see mem use exit(0); }
另外你可以添加一个像这样的调用: pthread_attr_setguardsize(&thread_attr, 0);
就在调用pthread_attr_setstacksize()
但是你完全没有检测到栈溢出检测,它只会为你节省4k的地址空间和零实际内存。
你是否想要搜索一个公式来计算每个进程可能的最大线程数?
Linux间接实现每个进程的最大线程数量!
number of threads = total virtual memory / (stack size*1024*1024)
因此,通过增加总虚拟内存或减小堆栈大小,可以增加每个进程的线程数量。 但是,如果最大虚拟内存等于交换内存,则堆栈大小的减少会导致堆栈溢出导致代码失败。
检查你的机器:
总虚拟内存: ulimit -v
(默认是无限的,因此你需要增加交换内存来增加这个)
总堆栈大小: ulimit -s
(默认是8Mb)
增加这些值的命令:
ulimit -s newvalue ulimit -v newvalue
*用您想要作为限制的值替换新值。
参考文献:
http://dustycodes.wordpress.com/2012/02/09/increasing-number-of-threads-per-process/