410 Stimmen

Wie viele Threads sind zu viele?

Ich schreibe einen Server, und ich sende jede Aktion in einen separaten Thread, wenn die Anforderung empfangen wird. Ich tue dies, weil fast jede Anfrage eine Datenbankabfrage macht. Ich verwende eine Threadpool-Bibliothek, um die Konstruktion/Destruktion von Threads zu reduzieren.

Meine Frage ist: Was ist ein guter Grenzwert für E/A-Themen wie diese? Ich weiß, es wäre nur eine grobe Schätzung, aber reden wir von Hunderten? Tausenden?

Wie könnte ich herausfinden, wie hoch dieser Grenzwert ist?


EDITです。

Ich danke Ihnen allen für Ihre Antworten. Es sieht so aus, als müsste ich es einfach ausprobieren, um meine Obergrenze für die Fadenzahl herauszufinden. Die Frage ist allerdings: Woher weiß ich, dass ich diese Grenze erreicht habe? Was genau sollte ich messen?

282voto

paxdiablo Punkte 809679

Einige Leute würden sagen, dass zwei Fäden zu viele sind - ich gehöre nicht ganz dazu :-)

Hier ist mein Ratschlag: Messen Sie, raten Sie nicht. Ein Vorschlag wäre, den Wert konfigurierbar zu machen und ihn zunächst auf 100 zu setzen, dann die Software freizugeben und zu beobachten, was passiert.

Wenn Ihre Fadennutzung bei 3 liegt, dann sind 100 zu viel. Wenn sie den größten Teil des Tages bei 100 bleibt, erhöhen Sie sie auf 200 und sehen Sie, was passiert.

Vous かも Eigentlich könnte Ihr Code selbst die Nutzung überwachen und die Konfiguration für den nächsten Start anpassen, aber das ist wahrscheinlich übertrieben.


Zur Klarstellung und Ausarbeitung:

Ich plädiere nicht dafür, ein eigenes Thread-Pooling-Subsystem zu entwickeln, verwenden Sie auf jeden Fall das, das Sie haben. Aber da Sie nach einem guten Grenzwert für Threads gefragt haben, nehme ich an, dass Ihre Thread-Pool-Implementierung die Möglichkeit hat, die maximale Anzahl der erstellten Threads zu begrenzen (was eine gute Sache ist).

Ich habe Thread- und Datenbankverbindungs-Pooling-Code geschrieben, und sie haben die folgenden Eigenschaften (die meiner Meinung nach für die Leistung wesentlich sind):

  • eine Mindestanzahl aktiver Threads.
  • eine maximale Anzahl von Threads.
  • die Schließung von Themen, die eine Zeit lang nicht benutzt wurden.

Die erste legt eine Mindestleistung für den Thread-Pool-Client fest (diese Anzahl von Threads steht immer zur Verfügung). Die zweite legt eine Beschränkung der Ressourcennutzung durch aktive Threads fest. Die dritte kehrt in ruhigen Zeiten zur Grundlinie zurück, um die Ressourcennutzung zu minimieren.

Sie müssen die Ressourcennutzung durch ungenutzte Threads (A) gegen die Ressourcennutzung durch nicht genügend Threads zur Erledigung der Arbeit (B) abwägen.

(A) ist im Allgemeinen die Speichernutzung (Stacks usw.), da ein Thread, der keine Arbeit verrichtet, nicht viel von der CPU in Anspruch nimmt. (B) ist in der Regel eine Verzögerung bei der Verarbeitung der eingehenden Anfragen, da Sie warten müssen, bis ein Thread verfügbar wird.

Das ist der Grund, warum man misst. Wie Sie bereits erwähnt haben, wird die überwiegende Mehrheit Ihrer Threads auf eine Antwort von der Datenbank warten, so dass sie nicht ausgeführt werden. Es gibt zwei Faktoren, die sich darauf auswirken, wie viele Threads Sie vorsehen sollten.

Die erste ist die Anzahl der verfügbaren DB-Verbindungen. Dies kann eine harte Grenze sein, es sei denn, Sie können sie am DBMS erhöhen - ich gehe davon aus, dass Ihr DBMS in diesem Fall eine unbegrenzte Anzahl von Verbindungen aufnehmen kann (obwohl Sie das idealerweise auch messen sollten).

Die Anzahl der Fäden, die Sie haben sollten, hängt dann von Ihrer bisherigen Nutzung ab. Das Minimum, das Sie laufen lassen sollten, ist die Mindestanzahl, die Sie jemals laufen ließen + A%, mit einem absoluten Minimum von (zum Beispiel, und machen Sie es konfigurierbar wie A) 5.

Die maximale Anzahl von Threads sollte Ihrem historischen Maximum + B% entsprechen.

Sie sollten auch auf Verhaltensänderungen achten. Wenn Ihre Nutzung aus irgendeinem Grund über einen längeren Zeitraum 100 % des verfügbaren Volumens erreicht (so dass die Leistung der Clients beeinträchtigt wird), sollten Sie die zulässige Höchstgrenze erhöhen, bis sie wieder um B % niedriger ist.


Als Antwort auf die Frage "Was genau soll ich messen?":

Was Sie speziell messen sollten, ist die maximale Anzahl von Threads, die unter Last gleichzeitig verwendet werden (z. B. auf die Rückkehr des DB-Aufrufs warten). Fügen Sie dann einen Sicherheitsfaktor von 10% für ejemplo (Hervorhebung, da andere Poster meine Beispiele als feste Empfehlungen aufzufassen scheinen).

Darüber hinaus sollte dies in der Produktionsumgebung für die Abstimmung durchgeführt werden. Es ist in Ordnung, vorher eine Schätzung zu erhalten, aber man weiß nie, was in der Produktion auf einen zukommt (deshalb sollten alle diese Dinge zur Laufzeit konfigurierbar sein). Dies dient dazu, eine Situation wie die unerwartete Verdopplung der eingehenden Client-Anrufe aufzufangen.

46voto

Jay D Punkte 3105

Diese Frage wurde bereits ausführlich erörtert, und ich hatte nicht die Gelegenheit, alle Antworten zu lesen. Aber hier sind ein paar Dinge, die man berücksichtigen sollte, wenn man die Obergrenze für die Anzahl der gleichzeitigen Threads betrachtet, die in einem bestimmten System friedlich koexistieren können.

  1. Thread-Stack-Größe: Unter Linux beträgt die Standard-Thread-Stack-Größe 8 MB (Sie können ulimit -a verwenden, um sie herauszufinden).
  2. Maximaler virtueller Speicher, den eine bestimmte Betriebssystemvariante unterstützt. Linux Kernel 2.4 unterstützt einen Speicheradressraum von 2 GB. Mit Kernel 2.6 ist er etwas größer (3 GB).
  3. [1] zeigt die Berechnungen für die maximale Anzahl von Threads pro gegebener Max VM Supported. Für 2.4 sind es etwa 255 Threads. Für 2.6 ist die Zahl etwas größer.
  4. Welche Art von Kernel-Scheduler haben Sie? Vergleicht man den Kernel-Scheduler von Linux 2.4 mit dem von 2.6, so bietet der letztere ein O(1)-Scheduling ohne Abhängigkeit von der Anzahl der in einem System vorhandenen Aufgaben, während der erstere eher ein O(n) ist. So spielen auch die SMP-Fähigkeiten des Kernel-Schedulers eine gute Rolle bei der maximalen Anzahl von nachhaltigen Threads in einem System.

Jetzt können Sie die Stack-Größe anpassen, um mehr Threads zu integrieren, aber dann müssen Sie die Overheads der Thread-Verwaltung (Erstellung/Abbau und Scheduling) berücksichtigen. Sie können die CPU-Affinität für einen bestimmten Prozess sowie für einen bestimmten Thread erzwingen, um sie an bestimmte CPUs zu binden und so Thread-Migrations-Overheads zwischen den CPUs und Cold-Cash-Probleme zu vermeiden.

Beachten Sie, dass man nach Belieben Tausende von Threads erstellen kann, aber wenn Linux die VM ausgeht, fängt es einfach an, wahllos Prozesse (also Threads) zu beenden. Dies geschieht, um zu verhindern, dass das Utility-Profil ausgereizt wird. (Die Utility-Funktion gibt Auskunft über den systemweiten Nutzen für eine bestimmte Menge an Ressourcen. Bei konstanten Ressourcen, in diesem Fall CPU-Zyklen und Speicher, flacht die Nutzungskurve mit zunehmender Anzahl von Tasks ab).

Ich bin sicher, dass der Windows-Kernel-Scheduler auch etwas in dieser Art tut, um mit der Überbeanspruchung der Ressourcen umzugehen

[1] http://adywicaksono.wordpress.com/2007/07/10/i-can-not-create-more-than-255-threads-on-linux-what-is-the-solutions/

20voto

Andrew Grant Punkte 57342

Wenn Ihre Threads irgendeine Art von ressourcenintensiver Arbeit (CPU/Festplatte) ausführen, werden Sie selten mehr als ein oder zwei Vorteile sehen, und zu viele werden die Leistung sehr schnell beenden.

Im besten Fall kommen die späteren Threads zum Stillstand, während die ersten abgeschlossen werden, oder einige haben Blöcke mit geringem Overhead auf Ressourcen mit geringer Konkurrenz. Im schlimmsten Fall belasten Sie den Cache/die Festplatte/das Netzwerk und Ihr Gesamtdurchsatz sinkt in den Keller.

Eine gute Lösung ist es, Anfragen in einen Pool zu legen, die dann an Worker-Threads aus einem Thread-Pool weitergeleitet werden (und ja, die Vermeidung der ständigen Erstellung und Zerstörung von Threads ist ein guter erster Schritt).

Die Anzahl der aktiven Threads in diesem Pool kann dann auf der Grundlage der Ergebnisse der Profilerstellung, der verwendeten Hardware und anderer Faktoren, die auf dem Rechner auftreten können, angepasst und skaliert werden.

14voto

Chad Okere Punkte 4532

Eine Sache, die Sie bedenken sollten, ist, dass Python (zumindest die C-basierte Version) eine so genannte globale Interpretersperre die auf Multicore-Rechnern enorme Auswirkungen auf die Leistung haben können.

Wenn Sie wirklich das meiste aus dem Multithreading-Python herausholen wollen, sollten Sie vielleicht Jython oder ähnliches in Betracht ziehen.

9voto

bortzmeyer Punkte 32353

Wie Pax zu Recht sagte, messen, nicht raten . Das habe ich für DNS-Zeuge und die Ergebnisse waren überraschend: die ideale Anzahl von Threads war viel höher als ich dachte, etwa 15.000 Threads, um die schnellsten Ergebnisse zu erzielen.

Das hängt natürlich von vielen Dingen ab, deshalb muss man sich selbst messen.

Vollständige Maßnahmen (nur auf Französisch) in Wie viele Hinrichtungsfäden? .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X