Loading...

Die optimale Thread-Pool-Größe in Java: Eine Formel erklärt

Performance
9. August 2023
3 Minuten Lesezeit
Beitrag teilen:
Gefällt dir der Beitrag?
Du wirst den Newsletter lieben!

Das Bestimmen der optimalen Größe eines Thread Pools in Java ist entscheidend, um die Auslastung von CPU und Ressourcen zu maximieren. Diese Entscheidung hängt von vielen Faktoren ab. Hier zeigen wir dir, wie du die berühmte Formel aus Brian Goetz “Java Concurrency in Practice” verwenden kannst. Wir geben dir ein praktisches Beispiel, wie du das Verhältnis von Wartezeit zu Compute-Zeit (W/C) berechnen kannst.

Die Formel

Die Formel für die optimale Größe eines Thread Pools lautet:

int optimalThreadPoolSize = numberOfCores * targetUtilization * (1 + waitTime / computeTime);

Wo:

  • numberOfCores ist die Anzahl der CPUs, ermittelbar durch Runtime.getRuntime().availableProcessors().
  • targetUtilization ist die gewünschte CPU-Auslastung, ein Wert zwischen 0 und 1.
  • waitTime ist die durchschnittliche Zeiteinheit, die ein Thread, z.B. wegen I/O Operationen, wartet.
  • computeTime ist die durchschnittliche Zeiteinheit in der ein Thread echte Berechnungen durchführt.

Diese Formel hilft dir, die optimale Anzahl von Threads zu finden, um die Prozessoren bei der gewünschten Auslastung zu halten.

Wie man waitTime / computeTime berechnet

Angenommen, du hast einen Prozess, bei dem die Threads 20% ihrer Zeit mit Rechnen und 80% mit Warten auf I/O verbringen. Das Verhältnis von Wartezeit zu Compute-Zeit (W/C) wäre dann 4.

Diese Information kannst du in die Formel einfügen, um die optimale Thread-Pool-Größe zu berechnen.

In der Praxis musst du schätzen

In den meisten Fällen weißt du nicht exakt wie das Verhältnis zwischen Wait-/ und ComputeTime ist. Hier lohnt es sich mit begründeten Annahmen zu starten. Letztlich kannst du deine optimale Konfiguration nur mithilfe von gezielten Lasttests ermitteln. In den meisten Fällen wird dies aber mit der oben genannten Formel nicht notwendig sein.

Für Compute-Intensive Tasks

Wenn die Aufgaben hauptsächlich Berechnungen durchführen, erreichst du die optimale Auslastung mit numberOfCores + 1 Threads. Deine waitTime ist in diesem Fall 0.

Für I/O oder Blocking Operations

Wenn die Aufgaben I/O oder andere blockierende Operationen beinhalten, möchtest du einen größeren Pool, da nicht alle Threads ständig angesetzt werden können. Beispielsweise kannst du feststellen, dass in deinem Request ein Zugriff auf die Festplatte zum Lesen eines Files ca. 10 ms dauert. Der Rest deiner Businesslogik benötigt 5 ms. Damit ergibt sich für ein 4-Core System und angestrebter 80% CPU Utilization:

int optimalThreadPoolSize = 4 * 0.8 * (1 + 10 / 5); // 9,6

Somit ist eine Threadpoolgröße von 10 ein guter Start für diesen Teil der Applikation.

Was wir daraus lernen

Das Bestimmen der optimalen Thread-Pool-Größe in Java ist keine exakte Wissenschaft, aber mit einem Verständnis der Aufgaben und der Umgebung, in der sie ausgeführt werden, kann diese Formel eine starke Leitlinie bieten. Durch die Berücksichtigung von Faktoren wie Wartezeit und Compute-Zeit kannst du einen Thread Pool erstellen, der die Ressourcen deines Systems optimal nutzt.

Kennst du schon Marcus' Backend Newsletter?

Neue Ideen. 2x pro Woche!
Top