2010-08-19 11 views
5

si suppone Il seguente codice per fare 100.000 discussioni:NPTL limita le filettature massime a 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); 
} 

Questo è in esecuzione su un computer a 64 bit con 32 GB di RAM; Debian 5.0 installato, tutto disponibile.

  • ulimit -s 512 per mantenere la dimensione dello stack giù
  • /proc/sys/kernel/pid_max impostato su 1.000.000 (per impostazione predefinita, tappi fuori a 32K PID).
  • ulimit -u 1000000 per aumentare processi massimi (non credo che questo importa affatto)
  • /proc/sys/kernel/threads-max set a 1.000.000 (per impostazione predefinita, non è stato fissato a tutti)

l'esecuzione di questo sputa fuori il seguente:

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

non sto di certo a corto di RAM; Posso persino lanciare molti altri di questi programmi tutti in esecuzione contemporaneamente e tutti iniziano i loro thread da 65k.

(Si prega di astenersi dal suggerire, non provo a lanciare 100.000 discussioni. Questo è semplice test di qualcosa che dovrebbe. Il mio attuale server di epoll basata lavoro ha circa 200k + connessioni in ogni momento e various papers suggerirebbe che le discussioni solo potrebbe essere un'opzione migliore. - Grazie :))

+0

'ulimit -s 512' sets effettivamente la dimensione minima stack 512 kilobyte, non 512 byte. Quindi con 100.000 thread che sarebbero quasi 50 GB (tuttavia, questo probabilmente non è il problema, poiché gli stack sono allocati alla domanda). – caf

+0

Sì, ho provato a impostarlo su ulimit -s 1 e il risultato di 65528 thread è lo stesso. Lo stesso se uso ulimit -s 1024 per quella materia. – rekamso

+1

Puoi confermare con strazi (e pazienza) che la chiamata finale pthread_create (clone (2)?) Fallisce effettivamente con ENOMEM? Quali sono i valori di, e cosa succede se aumenti i file '/ proc/sys /': 'vm/max_map_count',' kernel/pid_max' e 'kernel/threads-max'? – pilcrow

risposta

6

menzione pilcrow di /proc/sys/vm/max_map_count è giusto in pista; l'aumento di questo valore consente l'apertura di più thread; non sono sicuro della formula esatta in questione, ma un valore di 1mil + consente alcuni thread di 300k +.

(Per chiunque altro a sperimentare con 100K + discussioni, non guardare pthread_create's mmap problemi ... fare nuove discussioni diventa veramente lento veramente veloce quando la memoria inferiore è esaurita.)

0

Un possibile problema è la variabile locale thread nel programma principale. Penso che pthread_t sarebbe 8 byte sulla tua macchina a 64-bit (assumendo la versione a 64-bit). Sarebbero 800.000 byte in pila. Il tuo limite di stack di 512K sarebbe un problema, penso. 512K/8 = 65536, che è sospettosamente vicino al numero di thread che stai creando. Potresti provare ad allocare dinamicamente quella matrice invece di metterla in pila.

+0

alternativamente lascia la dimensione dello stack da solo per il thread iniziale e cambialo solo per quelli successivi (es. Usa 'pthread_attr_setstack()' per impostare le dimensioni dello stack per ogni thread che crei) – Spudd86

0

Questo potrebbe aiutare a impostare la dimensione dello stack nel programma per i più piccoli si può andare (se ciò non bastasse si sceglie):

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

Inoltre si potrebbe aggiungere una chiamata in questo modo: pthread_attr_setguardsize(&thread_attr, 0); subito dopo la chiamata a pthread_attr_setstacksize(), ma poi si sarebbe sciolto pila di rilevamento superamento del tutto, e ti farebbe risparmiare solo 4k di spazio di indirizzamento e zero memoria reale.

0

Stai cercando di cercare una formula per calcolare i max thread possibili per processo?

Linux implementa il numero massimo di thread per processo indirettamente !!

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

Pertanto, il numero di fili per processo può essere aumentata aumentando la memoria virtuale totale o diminuendo dimensioni dello stack. Tuttavia, una riduzione eccessiva delle dimensioni dello stack può portare a un errore del codice a causa di un sovraccarico dello stack mentre la memoria virtuale massima è uguale alla memoria di scambio.

controlli la macchina:

Memoria virtuale totale: ulimit -v (di default è illimitato, quindi è necessario aumentare la memoria di swap per aumentare questo)

totale dimensione dello stack: ulimit -s (di default è 8MB)

comando per aumentare questi valori:

ulimit -s newvalue 

ulimit -v newvalue 

* Sostituire il nuovo valore con il valore che si desidera impostare come limite.

Riferimenti:

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