NPTL在65528处限制最大线程数?

下面的代码应该是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安装,所有股票。

  • ulimit -s 512保持堆栈大小
  • / proc / sys / kernel / pid_max设置为1,000,000(默认情况下,它在32k pid上加上)。
  • ulimit -u 1000000增加最大进程(不要以为这一点很重要)
  • / proc / sys / kernel / threads-max设置为1,000,000(默认情况下,根本没有设置)

运行这个吐出以下内容:

 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/