Maximale Anzahl (p)threads?



  • voidpointer schrieb:

    Hi,

    ich möchte eine Anfrage an ca. 60 Server anschicken, nur je ca. 20 bytes request und je ca. 20 bytes response (Timeout ca. 5 sekunden). Das ganze sollte aber möglichst schnell gehen, daher will ich nicht alles einzeln machen, sondern mit pthreads (am besten einen pthread pro Server).

    a.) Halten das auch nicht ganz so neue CPUs aus, 60 pthreads gleichzeitig zu starten?

    da 99% der zeit vermutlich gewartet wird, ist das der cpu egal.

    b.) Wie viele pthreads kann ich maximal starten?

    je nach OS muss man mit ca 1MB pro thread rechnen. 1000 duerften also 1GB ram ziehen.

    c.) Ist diese Idee sinnvoll oder eher nicht?

    eher nicht sinnvoll. mach dir lieber nur 60 sockets auf, schick die daten ab und lauf dann ein paar mal durch alle noch offenen sockets und teste ob was drinnen steht (sieh ioctlsocket + FIONREAD)
    ein taskswitch dauert tausend mal laenger als durchs array zu laufen 😉



  • hustbaer schrieb:

    und ich kenne pae, ja. bloss ob man das für stacks so ohne weiteres einsetzen kann...?

    wenn man das für ia32-systeme übliche 36bir pae ansetzt, ist der stack wohl eher die letzte sorge, die man hat. 32 byte pro thread als gesamtmenge an speicher, ist leider alles andere als berauschend. daher eher ohne stack und eigenen speicher. also ein bisschen rumgeschubse von registern, was aber beim ia32 auch nicht wirklich spaß macht. wäre aber sicher mal eine nette herausforderung das zu schaffen. (also für den fall, dass der scheduler da nicht vorher selbstmord begeht.)



  • Die Anzahl dürfte auch start OS Abhängig sein aber meines Wissens bekommt unter Linux jeder Thread eine eigenen PID und die PIDs müssen alle in 16bit passen -> 2¹⁶ Threads für Linux wenn sonst nichts läuft



  • da irrst du. die aktuelle linux pthread-implementierung unterstützt 2^31 threads (theoretisch).
    zum nachlesen hier: http://people.redhat.com/drepper/nptl-design.pdf



  • Vielen Dank für Eure Einschätzungen, ich denke, ich werde es mit asynchronuos IO versuchen - ganz schnell hintereinander jedem Server was senden und dann kriegen die alle ein lesendes select() mit Timeout hinterhergeschmissen (da select() ja kein polling ist, sollte das auch gut verkraftbar sein).

    Wenn ich übrigens auf meine Prozessliste schaue, werden die nie größer als ca. 32.000 (fangen danach wieder unten an), was zumindest auf meinem SuSE Linux 10.3 für signed 16 bit spricht.



  • voidpointer schrieb:

    Vielen Dank für Eure Einschätzungen, ich denke, ich werde es mit asynchronuos IO versuchen - ganz schnell hintereinander jedem Server was senden und dann kriegen die alle ein lesendes select() mit Timeout hinterhergeschmissen (da select() ja kein polling ist, sollte das auch gut verkraftbar sein).

    Wenn ich übrigens auf meine Prozessliste schaue, werden die nie größer als ca. 32.000 (fangen danach wieder unten an), was zumindest auf meinem SuSE Linux 10.3 für signed 16 bit spricht.

    So schauts aus, signed 16 bit wird auch benutzt (standardmäßig).



  • Hi,

    ich verstehe nicht so ganz, wozu du jedesmal einen Fred aufmachen willst. Hast Du 2^31 Netztwerkkarten? Du hast doch in jedem Fall eine Engstelle, durch die es nur langsam und seriell durchgeht, und das ist der Netzzugriff. Das ist wie mit der Baustelle auf der Autobahn. Es bringt für den Gesamtdurchsatz nichts, wenn Du von 6 Spuren auf 8 Spuren erweiterst, wenn am Ende eine einspurige Baustelle ist. Genau so ist es mit Deinem Problem. Das langsamste ist sowieso das Netz, und das ist nunmal seriell.

    Gruß Mümmel



  • @muemmel:
    Die Netzwerkkarte ist hier sicher nicht die Engstelle, denn es dauert unheimlich lange bis so ein Server im Internet antwortet.
    Und das Netz ist nicht in dem Sinn "seriell" dass man nicht mehrere Requests an mehrere Server gleichzeitig ausständig haben könnte. Das wäre ja ne Katastrophe wenn das nicht ginge. Es macht also durchaus Sinn quasi gleichzeitig mehrere Requests abzusetzen. Die Frage ist nur das wie, also ob mit Threads oder asynchronem IO oder nonblocking IO oder...



  • Hi,

    ist mir schon klar, daß die eigentliche Antwort viel langsamer ist als die Netzwerkkarte, denn die kann ja problemlos die volle vom Protokoll mögliche Datenrate.
    Aber INNERHALB Deines Rechners ist die Netzwerkkarte mit Sicherheit das langsamste Teil, denn sie muß von der heutezutage doch recht gewaltigen Geschwindigkeit des Prozessors runter auf das vergleichsweise langsame Tempo des Netzes transformieren.
    Sicher, das Netz selber ist nicht seriell, aber die Netzwerkkarte schon. Da geht immer nur ein Paket nach dem anderen durch. Was bringt es da, wenn die einzelnen Prozesse Schlange stehen, und warten bis sie was zu tun bekommen.
    Nicht vergessen, daß ein zusätzlicher Fred immer wesentlich mehr Overhead hat als nur einfach eine Funktion aufrufen. Wenn mehrere Prozesse, dann höchstens dahingehend, daß einer Deine Netzwerkkarte abfragt und wenn was da ist das dann an den zweiten übergibt zum Verarbeiten. Aber viele Prozesse starten lohnt schon deshalb nicht, weil Deine Maschine mit hoher Wahrscheinlichkeit nicht mehr als maximal 4 Kerne hat. Du vertust also im Endeffekt die Zeit blos damit, die Maschine von Fred zu Fred springen zu lassen statt zu arbeiten.
    Einen wirklichen Sinn macht es nur dann, wenn dadurch die eigentliche Programmierung für Dich einfacher und übersichtlicher wird. Aber leisungsmäßig holst Du da bestimmt nichts raus.

    Gruß Mümmel



  • muemmel, deiner Argumentation kann ich nicht ganz folgen. Vor allem was die Netzwerkkarte angeht. Dass mehrere Threads/Prozesse wohl nicht die beste Lösung ist wurde schon mehrfach geschrieben, hat aber mit der Netzwerkkarte nun garnix zu tun. Genauso eigentlich nicht mit der Zeit die beim Context-Switching draufgeht. Deine Argumentation "brauchste eigentlich garnicht" was Threads angeht lässt sich auch auf viele Bereiche anwenden wo oft Threads eingesetzt werden weil es einfach praktisch ist.



  • @muemmel dir ist schon klar, dass man die Übertragungsgeschwindigkeit einer Netzwerkkarte/-verbindung durch die Bandbreite misst und 60*40=2400Bytes quasiparallel übertragen werden (zusätzliche Bandbreite durch Ethernet, IP und TCP vernachlässigt).



  • Nun muss ich doch fragen, was hier nicht stimmt:

    // (foreach client (c_itr)
    				*c_itr = new Client(s_itr->ip.c_str(), s_itr->port, eUDP);
    
    		// (foreach client (c_itr)
    			(*c_itr)->send("\\status\\",8);
    
    		sleep(3); // TIMEOUT
    	        // (foreach client (c_itr)
                    {
    			char buffer[1024];
                            (*c_itr)->recv(buffer, 1024);
    			puts("done...");
                    }
    
    		// (foreach client (c_itr)
    			delete *c_itr;
    

    Das ist jetzt mehr oder weniger Pseudo-Code. Zuerst connected er zu allen servern der Reihe nach, danach sendet er der Reihe nach jedem Server eine Message. Dann sollte er nach 3 Sekunden von jedem Server die Response empfangen.

    Allerdings hängt er nach ca. 10 von 100 Servern beim recv() fest (dieses Client::recv() macht vorher einen select()-call mit Timeout - aber das Timeout wird hier überschritten und es passiert nichts)...

    Geht das so überhaupt? Kann ich hundert Servern nen Request schicken, so dass die alle ihre Nachrichten auf meinem Socket "speichern"? Ist der Speicherplatz meines Sockets vielleicht begrenzt? (Die Antworten müssten zusammen ca. 30 kb groß sein).

    BTW: Wireshark sagt mir auch nur, dass alle 100 send-Befehle geklappt haben, aber nur die ca. 10 erwähnten Nachrichten eingegangen sind.



  • Da es hier vermutlich sowieso um Linux geht eigetlich hinfällig aber:

    Windows läßt nur eine bestimmte anzahl gleichzeitiger verbindungen zu solange man es nicht in der Registry ändert.
    IMHO bei XP 10.



  • Windows läßt nur eine bestimmte anzahl gleichzeitiger verbindungen zu solange man es nicht in der Registry ändert.
    IMHO bei XP 10.

    Du meinst das Half-Open Connection Limit.



  • Jo das meint er, und das lässt sich gottseidank patchen.

    Man guckt im Event-Log nach dem Eintrag, notiert sich die EventID, sucht damit im Google -> findet den Patch -> lädt ihr herunter -> installiert ihn -> hat Ruhe. Oder so ähnlich 🙂

    @voidpointer:
    Wenn du recv nur auf die Sockets versuchst wo select() auch hingehaut hat, dann sollte es gehen. Wenn du bloss vorher select() machst und dann trotzdem auf alle Sockets ein recv machst ist es klar dass es blockieren wird.



  • Hmm die Frage die ich eigentlich hatte war:
    -Wenn der Server etwas send()et, aber der Client erst 3 Sekunden später recv()ed... wo werden die zwischengespeichert?
    -Könnte es passieren, dass alle Messages, die noch nicht empfangen wurden, aber schon vom Server geschickt wurden, auf irgendeinem Buffer beim Client gespeichert werden, und wenn dieser Buffer voll ist, keine weiteren send()s der Server zugelassen werden?



  • also dein os hat ein-/ausgans-fifo-caches für quasi alle io-operationen. wie groß der ist, ist systemabhängig und dein system regelt bei synchronen zugriffen auch, dass der nicht überlaufen kann, in dem er bspw bei netzwerkclients die empfangsbestätigung verweigert oder aktiv mitteilt, dass es zu schnell geht.
    bei async liegt je nach system ein teil der verantwortng bei dir.



  • @vp:
    Der Sender-PC puffert es solange bis er vom Empfänger-PC die Bestätigung bekommen hat dass dieser es nun empfangen & gepuffert hat. Der Empfänger-PC puffert es dann solange bis das Empfänger-Programm es abholt.
    Wenn das Empfänger-Programm sich zu lange Zeit lässt, oder der Sender-PC zu schnell Daten schickt, dann kann es sein dass die max. Grösse des Empfangspuffers beim Empfänger-PC erreicht wird.
    Macht aber nix, weil der Empfänger-PC dem Sender-PC auch ständig mitteilt wie viel von seinem Puffer noch frei ist. Der Sender-PC hört dann, wenn laut seinen Informationen im Empfänger-Puffer nichtmehr genug Platz ist, automatisch auf neue Daten zu schicken bis er wieder vom Empfänger-PC gehört hat dass wieder Platz in dessen Puffer frei ist.



  • Danke hustbaer, das hilft mir!

    hustbaer schrieb:

    Macht aber nix, weil der Empfänger-PC dem Sender-PC auch ständig mitteilt wie viel von seinem Puffer noch frei ist. Der Sender-PC hört dann, wenn laut seinen Informationen im Empfänger-Puffer nichtmehr genug Platz ist, automatisch auf neue Daten zu schicken bis er wieder vom Empfänger-PC gehört hat dass wieder Platz in dessen Puffer frei ist.

    Gilt das auch bei UDP? Und wie lange macht der Sender PC das mit?



  • Vielleicht wäre es angebracht, wenn du dich mal intensiver mit der TCP/IP Protokollfamilie auseinandersetzt um ein besseres Verständnis dafür zu bekommen 🙂

    Was sind diese half-open Connections?


Anmelden zum Antworten