2010-08-19 8 views
5

El siguiente código se supone que hace 100.000 hilos:NPTL tapa los hilos máximos en 65528?

/* 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); 
} 

Esto se ejecuta en una máquina de 64 bits con 32 GB de RAM; Debian 5.0 instalado, todo el stock.

  • ulimit -s 512 para mantener el tamaño de la pila hacia abajo
  • /proc/sys/kernel/pid_max ajustado a 1.000.000 (de forma predeterminada, los casquillos a cabo a 32k PIDS).
  • ulimit -u 1000000 para aumentar los procesos de Max (no creo que esto es importante en todos)
  • /proc/sys/kernel/conjunto de hilos-max y 1.000.000 (de manera predeterminada, no ha sido configurada en absoluto)

la ejecución de este escupe lo siguiente:

65500 threads so far ... 
Failed with return code 12 creating thread 65529 (Cannot allocate memory). 
Malloc worked, hmmm 

Desde luego, no estoy quedando sin memoria rAM; Incluso puedo lanzar varios más de estos programas que se ejecutan todos al mismo tiempo y todos comienzan sus hilos de 65k.

(Por favor, abstenerse de sugerir que no trato de lanzar 100.000 hilos. Esto es simple prueba de algo que debe trabajo. Mi servidor actual basado en epoll tiene aproximadamente 200 k + conexiones en todo momento y various papers sugeriría que las discusiones solo podría ser una mejor opción. - Gracias :))

+0

'ulimit -s 512' realmente establece el tamaño mínimo de pila a 512 kilobytes, no 512 bytes. Entonces, con 100,000 hilos sería casi 50GB (sin embargo, este no es el problema, ya que los stacks están asignados por demanda). – caf

+0

Sí, he intentado configurarlo simplemente como ulimit -s 1 y el resultado de 65528 hilos es el mismo. Lo mismo si uso ulimit -s 1024 para ese asunto. – rekamso

+1

¿Puede confirmar con strace (y paciencia) que la llamada final pthread_create (clone (2)?) En realidad falla con ENOMEM? ¿Cuáles son los valores de y qué ocurre si aumenta los archivos '/ proc/sys /': 'vm/max_map_count',' kernel/pid_max' y 'kernel/threads-max'? – pilcrow

Respuesta

6

La mención de pilcrow de /proc/sys/vm/max_map_count va por buen camino; elevar este valor permite que se abran más hilos; no estoy seguro de la fórmula exacta involucrada, pero un valor de 1mil + permite unos 300k + hilos.

(Para cualquier otra persona experimentando con 100k + hilos, se fijan en pthread_create's mmap cuestiones ... haciendo nuevos temas se pone muy lento muy rápido cuando la memoria inferior se utiliza para arriba.)

0

Un posible problema es la variable local thread en el programa principal. Creo que pthread_t sería de 8 bytes en tu máquina de 64 bits (suponiendo una compilación de 64 bits). Eso sería 800,000 bytes en la pila. Su límite de stack de 512K sería un problema, creo. 512K/8 = 65536, que sospechosamente está cerca del número de subprocesos que está creando. Puede intentar asignar dinámicamente esa matriz en lugar de ponerla en la pila.

+0

alternativamente, deje el tamaño de pila solo para el hilo inicial y cámbielo solo para los posteriores (es decir, use 'pthread_attr_setstack()' para establecer el tamaño de pila para cada hilo que cree) – Spudd86

0

Esto podría ayudar a establecer el tamaño de la pila en el programa para el más pequeño que puede ir (si eso no es suficiente a escoger):

/* 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); 
} 

, además, le podría añadir una llamada como esta: pthread_attr_setguardsize(&thread_attr, 0); justo después de la llamada a pthread_attr_setstacksize() pero entonces habría perder detección de saturación de pila por completo, y solo le ahorraría 4k de espacio de direcciones y cero memoria real.

0

¿Está tratando de buscar una fórmula para calcular los hilos máximos posibles por proceso?

Linux implementa el número máximo de hilos por proceso indirectamente !!

number of threads = total virtual memory/(stack size*1024*1024) 

Así, el número de hilos por proceso se puede aumentar mediante el aumento de la memoria virtual, total o por la disminución de tamaño de la pila. Sin embargo, disminuir demasiado el tamaño de la pila puede provocar una falla en el código debido al desbordamiento de la pila, mientras que la memoria virtual máxima es igual a la memoria de intercambio.

devolver a la salida de la máquina:

memoria virtual total: ulimit -v (por defecto es ilimitado, por tanto, es necesario aumentar la memoria de intercambio para aumentar este)

total tamaño de la pila: ulimit -s (por defecto es de 8 Mb)

Comando para aumentar estos valores:

ulimit -s newvalue 

ulimit -v newvalue 

* Reemplace el nuevo valor con el valor que desea poner como límite.

Referencias:

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

Cuestiones relacionadas