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);
}
Это работает на 64-битной машине с 32 ГБ оперативной памяти; Debian 5.0 установлен, все сток.
- ulimit -s 512, чтобы уменьшить размер стека
- Для /proc/sys/kernel/pid_max установлено значение 1,000,000 (по умолчанию он ограничен 32 тыс. пид).
- 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
Я, конечно, не хватает баранов; Я даже могу запустить еще несколько этих программ, работающих одновременно, и все они запускают свои потоки по 65 тыс.
(Пожалуйста, воздержитесь от предложения, чтобы я не пытался запускать более 100 000 потоков. Это простое тестирование того, что должно работать. Мой текущий сервер на основе epoll всегда имеет около 200 000 подключений +, и в различных статьях можно предположить, что потоки могут быть лучшим вариантом.. - Спасибо:))
4 ответа
Упоминание Пикроу о /proc/sys/vm/max_map_count
находится на правильном пути; повышение этого значения позволяет открывать больше потоков; не уверен в точной формуле, но значение 1mil+ учитывает около 300k+ потоков.
(Для всех, кто экспериментирует с потоками 100k +, посмотрите на проблемы mmap в pthread_create... создание новых потоков становится очень медленным и очень быстрым, когда используется меньше памяти.)
Это может помочь установить размер стека в программе на наименьшее значение (если этого недостаточно, вы выбираете):
/* 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()
но тогда вы полностью потеряете обнаружение переполнения стека, и это сэкономит вам только 4 Кб адресного пространства и ноль фактической памяти.
Одной из возможных проблем является локальная переменная thread
в основной программе. Я думаю, что pthread_t будет 8 байтов на вашей 64-битной машине (при условии 64-битной сборки). Это было бы 800 000 байтов в стеке. Ваш предел стека в 512К был бы проблемой, я думаю. 512K / 8 = 65536, что подозрительно близко к числу создаваемых вами потоков. Вы можете попытаться динамически выделить этот массив вместо помещения его в стек.
Вы пытаетесь найти формулу для расчета максимально возможных потоков на процесс?
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/