2010-08-19 8 views
5

Le code suivant est censé faire: 100.000 filsNPTL limite le nombre maximum de threads à 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); 
} 

Ceci est en cours d'exécution sur une machine 64 bits avec 32 Go de RAM; Debian 5.0 installé, tous les stocks.

  • ulimit -s 512 pour maintenir la taille de la pile vers le bas
  • /proc/sys/kernel/pid_max mis à 1000000 (par défaut, il plafonne à 32k sur PIDS).
  • ulimit -u 1000000 pour augmenter les processus max (ne pense pas que cela importe du tout)
  • /proc/sys/kernel/set threads-max à 1.000.000 (par défaut, il n'a pas été fixé à tous)

l'exécution de cette recrache les éléments suivants:

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

Je ne suis certainement pas manquer de RAM; Je peux même lancer plusieurs de ces programmes tous en même temps et ils commencent tous leurs threads 65k.

(S'il vous plaît ne pas suggérer que j'essaie de ne pas lancer 100.000+ threads. Ceci est un simple essai de quelque chose qui devrait travail. Mon serveur basé epoll courant a environ 200k + connexions à tout moment et various papers suggère que les discussions juste peut être une meilleure option - Merci :))

+0

'ulimit -s 512' définit en fait la taille minimale de la pile à 512 kilo-octets, et non pas 512 octets. Donc, avec 100 000 threads qui seraient presque 50 Go (cependant, ce n'est probablement pas le problème, car les piles sont allouées à la demande). – caf

+0

Oui, j'ai essayé de le définir simplement à ulimit -s 1 et le résultat de 65528 threads est le même. Pareil si j'utilise ulimit -s 1024 d'ailleurs. – rekamso

+1

Pouvez-vous confirmer avec strace (et patience) que l'appel final pthread_create (clone (2)?) Échoue réellement avec ENOMEM? Quelles sont les valeurs de, et que se passe-t-il si vous augmentez les fichiers '/ proc/sys /': 'vm/max_map_count',' kernel/pid_max' et 'kernel/threads-max'? – pilcrow

Répondre

6

la mention de pilcrow de /proc/sys/vm/max_map_count est sur la bonne voie; augmenter cette valeur permet d'ouvrir plus de threads; pas sûr de la formule exacte impliquée, mais une valeur de 1mil + permet des threads de 300k +.

(Pour toute personne expérimenter autre avec 100k + fils, ne regardez pthread_create's mmap questions ... faire de nouveaux threads devient vraiment très rapide lorsque la mémoire inférieure lente est utilisée.)

0

Un problème possible est la variable locale thread dans le programme principal. Je pense que pthread_t serait 8 octets sur votre machine 64 bits (en supposant que la construction 64 bits). Ce serait 800 000 octets sur la pile. Votre limite de pile de 512K serait un problème je pense. 512K/8 = 65536, ce qui est étrangement proche du nombre de threads que vous créez. Vous pouvez essayer d'allouer dynamiquement ce tableau au lieu de le placer sur la pile.

+0

laissez alternativement la taille de la pile pour le thread initial et ne le changez que pour les threads suivants (c'est-à-dire utilisez 'pthread_attr_setstack()' pour définir la taille de la pile pour chaque thread que vous créez) – Spudd86

0

Cela pourrait aider à définir la taille de la pile dans la programme le plus petit, il peut aller (si cela ne suffit pas vous choisissez):

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

en outre, vous pouvez ajouter un appel comme celui-ci: pthread_attr_setguardsize(&thread_attr, 0); juste après l'appel à pthread_attr_setstacksize() mais vous perdriez détection de dépassement de pile entièrement, et cela ne vous ferait économiser que 4k d'espace d'adressage et zéro mémoire réelle.

0

Essayez-vous de rechercher une formule pour calculer les threads max possibles par processus?

Linux implémente un nombre maximal de threads par processus indirectement !!

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

Ainsi, le nombre de fils par procédé peut être augmentée en augmentant la mémoire virtuelle totale ou en diminuant la taille de la pile. Cependant, une taille de pile trop faible peut entraîner une défaillance du code en raison d'un débordement de pile, alors que la mémoire virtuelle maximale est égale à la mémoire d'échange.

-vous vérifier machine:

Mémoire virtuelle totale: ulimit -v (par défaut est illimité, donc vous devez augmenter la mémoire d'échange pour augmenter cette)

total Taille de la pile: ulimit -s (par défaut 8Mo)

commande pour augmenter ces valeurs:

ulimit -s newvalue 

ulimit -v newvalue 

* Remplacez la nouvelle valeur par la valeur que vous voulez définir comme limite.

Références:

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

Questions connexes