NPTL ограничивает максимальные потоки в 65528? - PullRequest
5 голосов
/ 19 августа 2010

Следующий код должен создать 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 всегда имеет примерно 200k + подключений и различные документы предполагают, что потоки могут быть лучшим вариантом. - Спасибо :))

Ответы [ 4 ]

6 голосов
/ 19 августа 2010

упоминание Пилкроу /proc/sys/vm/max_map_count верно;повышение этого значения позволяет открывать больше потоков;не уверен в точной формуле, но значение 1mil + учитывает около 300k + потоков.

(Для всех, кто экспериментирует с потоками 100k +, посмотрите проблемы mmap в pthread_create ... создание новыхпотоки становятся очень медленными и очень быстрыми, когда используется меньше памяти.)

0 голосов
/ 09 февраля 2012

Вы пытаетесь найти формулу для расчета максимально возможного количества потоков на процесс?

Linux реализует максимальное количество потоков на процесс косвенно !!

number of threads = total virtual memory / (stack size1024)

Таким образом, количество потоков на процесс может быть увеличено путем увеличения общей виртуальной памяти или уменьшения размера стека.Но слишком большое уменьшение размера стека может привести к сбою кода из-за переполнения стека, в то время как максимальное количество виртуальной памяти равно объему подкачки.

Проверьте свой компьютер:

ВсегоВиртуальная память: ulimit -v (значение по умолчанию не ограничено, поэтому вам необходимо увеличить объем подкачки, чтобы увеличить его)

Общий размер стека: ulimit -s (по умолчанию 8 МБ)

Командачтобы увеличить эти значения: *1024*

ulimit -s newvalue

ulimit -v newvalue

* Замените новое значение значением, которое вы хотите установить в качестве предела.

Ссылки:

http://dustycodes.wordpress.com/2012/02/09/increasing-number-of-threads-per-process/

0 голосов
/ 22 ноября 2010

Это может помочь установить размер стека в программе как можно меньшим (если этого недостаточно, вы выбираете):

/* 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 Кб адресного пространства и ноль фактической памяти.

0 голосов
/ 19 августа 2010

Одной из возможных проблем является локальная переменная thread в основной программе. Я думаю, что pthread_t будет 8 байтов на вашей 64-битной машине (при условии 64-битной сборки). Это было бы 800 000 байтов в стеке. Ваш предел стека в 512К был бы проблемой, я думаю. 512K / 8 = 65536, что подозрительно близко к числу создаваемых вами потоков. Вы можете попытаться динамически выделить этот массив вместо помещения его в стек.

...