threads mit fork werden langsamer
-
Hi,
ich habe hier ein Problem, dessen Ursache mir nicht ganz klar ist. Im Prinzip geht es darum, dass (POSIX) Threads einen Prozess forken. Mein Problem ist nun, dass die Bearbeitungszeit jedes neuen Threads mit der Zeit immer laenger wird.
Hier ein Beispiel:
#include <time.h> #include <unistd.h> #include <pthread.h> #include <sys/types.h> void * do_fork(void *args) { int s; clock_t now, then; float time; then = clock(); if (fork()) { /* spend some time */ for(s = 0; s < 999; s++) { s++;s--;s++;s--; } pthread_exit(0); } wait(&s); now = clock(); time = (float) abs(then - now) / (float) CLOCKS_PER_SEC; printf("%.8f\n", time); pthread_exit(0); } int main() { int i,j; pthread_t t[200 * 10]; for (j = 0; j < 10; j++) { for (i = 0; i < 200; i++) { pthread_create(&t[i], 0, do_fork, 0); } for (i = 0; i < 200; i++) { pthread_join(t[i], 0); } } return 0; }
Es werden stets 200 Threads erzeugt, auf deren Beendigung danach gewartet wird. Dies geschieht 10 mal. In der thread-Routine wird fork() aufgerufen, die Zeit gemessen und ausgegeben. Die ersten paar Threads werden bei mir in etwa 0.0078 Sekunden abgearbeitet. Das schraubt sich dann allerdings hoch bis zu den letzten mit 0.96 Sekunden.
Warum ist das so? Eine weitere Unerklaerlichkeit: Wenn ich nach der Threadgenerierung den Prozess ein bisschen schlafen lasse, dann sind alle Threads im allgemeinen schneller (letzter Prozess in 0.65 Sekunden):
for (i = 0; i < 200; i++) { pthread_create(&t[i], 0, do_fork, 0); usleep(100); }
haeh?
Noch eine andere Kleinigkeit:
Wie beendet man einen geforkten Prozess aus einem Thread richtig. Mit pthread_exit()?viele Gruesse
-
was für einen sinn hat es für threads nochmal extra zu forken ?
das wird proportional zur anzahl der threads teurer
und einen prozess beendet man mit exit nicht mit pthread_exit
-
was für einen sinn hat es für threads nochmal extra zu forken ?
execve, zum Beispiel.
-
Überleg mal was du machst!
Du hast sagen wir 3 Threads die sich 1 mal forken.
Der 1 Thread forkt sich dann haste:
2 Prozesse mit einem ThreadIn beiden Prozessen wird nun ein neuer Thread erzeugt der sich forkt:
Jetzt haste 4 Prozesse mit 2 ThreadsDei 4 Prozesse erzeugen nun jeweils einen dritten Thread in sich, der diesen Prozess wiederum forkt.
Jetzt haste 8 Prozesse mit 3 Threads.Wie du siehst verdoppelt sich die Anzahl der Prozesse bei jedem neuen Thread.
Da brauchst du dich nciht wundern wenn die späteren Threads so langsam sind.Abgesehn davon ist der Code nciht sinnvoll, normalerweise forkt man
einen Prozess erst und macht dann Threads (apache macht das glaub ich so)
-
Storm.Xapek.de schrieb:
Wie du siehst verdoppelt sich die Anzahl der Prozesse bei jedem neuen Thread.
Da brauchst du dich nciht wundern wenn die späteren Threads so langsam sind.Das ist nicht der Fall. Bei Pthreads hat ein fork() den folgenden Effekt (unter anderem):
- Es wird ein neuer Prozess mit nur EINEM Thread erzeugt. Es ist der Thread der fork() aufruft.
- Damit gibt es keine Verdopplung mit jedem Aufruf von fork()
-
nl_u schrieb:
Noch eine andere Kleinigkeit:
Wie beendet man einen geforkten Prozess aus einem Thread richtig. Mit pthread_exit()?Nimm einfach exit().
Zu deinem ursprünglichen Probelem sind mir folgende Dinge aufgefallen, die es hier besser machen:
- fork() gibt dem Child 0 zurück. Deshalb sollte die if Abfrage if (fork() == 0) heissen.
- Ein Thread sollte auf genau sein Child warten: pid = fork(); ... ; waitpid(pid, NULL, 0);
- Mehrere Threads konkurrieren um printf was nicht thread-safe ist. Benutze einen Mutex und fprintf(stderr, ...) hier.
- Miss die Zeit mit gettimeofday und nicht mit clock().
-
Das hier geht. Ich muss aber noch klären, warum ich Probleme mit stdout habe.
#include <time.h> #include <unistd.h> #include <pthread.h> #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <sys/times.h> pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; void * do_fork(void *args) { int s; double time; struct timeval now, then; gettimeofday(&then, NULL); if (!fork()) { /* spend some time */ for(s = 0; s < 999; s++) { s++;s--;s++;s--; } pthread_exit(0); } wait(&s); gettimeofday(&now, NULL); time = now.tv_sec - then.tv_sec + 1e-6*(now.tv_usec - then.tv_usec); pthread_mutex_lock(&mutex); fprintf(stderr, "%.8f\n", time); pthread_mutex_unlock(&mutex); pthread_exit(0); } int main() { int i,j; pthread_t t[200 * 10]; for (j = 0; j < 10; j++) { for (i = 0; i < 200; i++) { pthread_create(&t[i], 0, do_fork, 0); } for (i = 0; i < 200; i++) { pthread_join(t[i], 0); } } return 0; }
-
Hey, danke fuer eure Bemuehungen. Ich habe die Ursache ausfindig machen koennen und muss zu meiner Schande gestehen, dass es erstens sehr daemlich und zweitens nichts mit den threads zu tun hat. Es war ein Memory-Leak.
Im tatsaechlichen Programm hatte ich vor pthread_create ein strdup. Mit jeder Threaderzeugung wurde somit Speicher allokiert, der auch nach Beendigung des Threads nicht freigegeben wurde. Das hat das ganze Programm schrittweise verlangsamt.Sorry Leute