Hallo
Ich möchte grössere Datenmengen verarbeiten und versuche deshalb Jobs auf mehrere Prozesse zu verteilen.
Das Aufteilen, der Respawn und die Kommunikation funktioniert wunderbar. Jedoch sind die Ergebnisse nicht wie zu erwarten. Wenn ich keine CPU-Leistung abrufe, verhält es sich wie erwartet. Mit steigender Anzahl an Prozessen verringert sich die Ausführungszeit. Wenn ich aber leistungsintensive Funktionen ausführe, skaliert das überhaupt nicht mit der Prozessanzahl.
Ich starte hiermit einen neuen Prozess:
Während des Programmierens habe ich eine Situation simuliert, welche einem API-Aufruf oder sonstiger I/O-Last entspricht.
Hat alles wie erwartet funktioniert. Ich konnte Problemlos hundert Prozesse parallel starten.
Dann wollte ich testen wie sich das Skript verhält, wenn ich CPU-Leistung in den Prozessen abrufe. Da hatte ich (unter Windows) mit den ersten Versuchen nicht viel Erfolg, da der Hauptprozess irgendwie überfordert war, die CPU sich aber gelangweilt hat.
Also habe ich den usleep gegen folgendes getauscht.
Diese Code dauerte auf einem Kern etwa 2,5 Sekunden, wohl abhängig von der Zufallszahl, und entsprach somit etwas dem usleep von zuvor. Bei den Tests ist mir dann aber aufgefallen, dass die Anzahl der Prozesse NULL Auswirkung auf die Summe der Laufzeit hat. Habe dann mehrfach geprüft ob die Prozesse richtig starten, ob das Code ausgeführt wird und ob die Rückgabe stimmt. Habe mir dann auch mit PHP ausgeben lassen wie viele (der 100 Jobs) noch ausstehend sind, wie viele Prozesse aktuell offen sein müssen und wie viele Prozesse erfolgreich abgeschlossen wurden. Die Ausgaben passen zu dem, was ich mit htop & Co. auslesen kann. Ich sehe die neu gestarteten Prozesse, die alten abgeschlossenen und die Ausgabe passt zu dem, was der Code machen soll. Jedoch kann man sagen, dass mit Verdoppelung der Prozesse, die Ausführungszeit pro Prozess sich gleich mit verdoppelt. Selbst dann, wenn die Anzahl paralleler Prozesse unter der Anzahl freier Kerne liegt.
Hier die Tabelle dazu (Jeweils 100 Jobs zu erledigen)
Würde man die Tests mehrfach wiederholen, würden sich die kleinen Unterschiede in der Dauer mit Sicherheit glätten. Also kann man sagen, die Dauer ist immer gleich. Obwohl die CPU-Auslastung extrem ansteigt.
Habe dann mal noch ein paar Tests mit doppelten (16) Kernen gemacht.
Ab hier bin ich raus und konnte mir das Ergebnis überhaupt nicht mehr erklären.
1. Warum bringt eine 8-fache Rechenleistung (1 Kern zu 8 Kernen) keinen Vorteil, sondern verlängert die Laufzeit der Prozesse OBWOHL 8 Kerne auf Anschlag 100% laufen?
2. Was läuft bei den 16 Kernen falsch?
Zum System selbst
Ich hab das jetzt auf einer Debian VM unter Proxmox mit 8 und 16 Kernen und 8GB RAM getestet. PHP ist 8.0. Mit und ohne opcache macht keinen Unterschied. Ausgeführt auf CLI.
Host ist ein AMD Epyc mit 48 Kernen. Es laufen noch andere VMs auf dem System. Die meisten sind irgendwelche 2-Kern Systeme, die nichts zu tun haben max. 1% Auslastung haben. Lediglich eine grosse Windows VM mit 32 Kernen döddelt mit 5-10% Auslastung vor sich hin. Aber selbst wenn ich die Test-VM auf allen Kernen voll belaste, bringt das auf dem Host keine 50% Auslastung.
Ich habe keine Idee, woran das liegen kann.
Ich möchte grössere Datenmengen verarbeiten und versuche deshalb Jobs auf mehrere Prozesse zu verteilen.
Das Aufteilen, der Respawn und die Kommunikation funktioniert wunderbar. Jedoch sind die Ergebnisse nicht wie zu erwarten. Wenn ich keine CPU-Leistung abrufe, verhält es sich wie erwartet. Mit steigender Anzahl an Prozessen verringert sich die Ausführungszeit. Wenn ich aber leistungsintensive Funktionen ausführe, skaliert das überhaupt nicht mit der Prozessanzahl.
Ich starte hiermit einen neuen Prozess:
PHP-Code:
require_once __DIR__.'/../helper/autoregister.php';
$stream = new Stream(STDOUT, STDIN, STDERR);
$data = $stream->read();
$watchdog = new Watchdog($data['config']);
$watchdog->watch();
$stream->write('Done');
PHP-Code:
class Watchdog {
public function __construct(array $config){
}
public function watch(){
usleep(rand(2000000,3000000));
}
}
Kerne | Prozesse | Dauer | Dauer pro Job | Proxmox CPU AGV |
16 | 2 | 122 | 2,44 | - |
16 | 4 | 66 | 2,64 | - |
16 | 8 | 32 | 2,56 | - |
16 | 16 | 17 | 2,72 | - |
16 | 32 | 9 | 2,88 | - |
16 | 50 | 6 | 3 | - |
16 | 100 | 3 | 3 | - |
Dann wollte ich testen wie sich das Skript verhält, wenn ich CPU-Leistung in den Prozessen abrufe. Da hatte ich (unter Windows) mit den ersten Versuchen nicht viel Erfolg, da der Hauptprozess irgendwie überfordert war, die CPU sich aber gelangweilt hat.
Also habe ich den usleep gegen folgendes getauscht.
PHP-Code:
class Watchdog {
public function __construct(array $config){
}
public function watch(){
$r = rand(10000,12000);
for($x = 0; $x !== $r; $x++){
hash('sha256', bin2hex(random_bytes(4096)).hash('sha512', bin2hex(random_bytes(4096))));
}
}
}
Hier die Tabelle dazu (Jeweils 100 Jobs zu erledigen)
Kerne | Prozesse | Dauer | Dauer pro Job | Proxmox CPU AGV |
8 | 1 | 276 | 2,76 | 12,50 % |
8 | 2 | 292 | 5,84 | 25,00 % |
8 | 3 | 296 | 8,88 | 37,50 % |
8 | 4 | 289 | 11,56 | 50,00 % |
8 | 6 | 291 | 17,46 | 75,00 % |
8 | 8 | 289 | 23,12 | 100,00 % |
8 | 10 | 288 | 28,8 | 100,00 % |
8 | 16 | 289 | 46,24 | 100,00 % |
8 | 25 | 290 | 72,5 | 100,00 % |
8 | 50 | 289 | 144,5 | 100,00 % |
8 | 75 | 291 | 218,25 | 100,00 % |
8 | 100 | 292 | 292 | 100,00 % |
Würde man die Tests mehrfach wiederholen, würden sich die kleinen Unterschiede in der Dauer mit Sicherheit glätten. Also kann man sagen, die Dauer ist immer gleich. Obwohl die CPU-Auslastung extrem ansteigt.
Habe dann mal noch ein paar Tests mit doppelten (16) Kernen gemacht.
Kerne | Prozesse | Dauer | Dauer pro Job | Proxmox CPU AGV |
16 | 2 | 259 | 5,18 | 12,50 % |
16 | 8 | 229 | 18,32 | 50,00 % |
16 | 16 | 245 | 39,2 | 16,00 % |
16 | 50 | 246 | 123 | 17,00 % |
16 | 100 | 242 | 242 | 17,00 % |
1. Warum bringt eine 8-fache Rechenleistung (1 Kern zu 8 Kernen) keinen Vorteil, sondern verlängert die Laufzeit der Prozesse OBWOHL 8 Kerne auf Anschlag 100% laufen?
2. Was läuft bei den 16 Kernen falsch?
Zum System selbst
Ich hab das jetzt auf einer Debian VM unter Proxmox mit 8 und 16 Kernen und 8GB RAM getestet. PHP ist 8.0. Mit und ohne opcache macht keinen Unterschied. Ausgeführt auf CLI.
Host ist ein AMD Epyc mit 48 Kernen. Es laufen noch andere VMs auf dem System. Die meisten sind irgendwelche 2-Kern Systeme, die nichts zu tun haben max. 1% Auslastung haben. Lediglich eine grosse Windows VM mit 32 Kernen döddelt mit 5-10% Auslastung vor sich hin. Aber selbst wenn ich die Test-VM auf allen Kernen voll belaste, bringt das auf dem Host keine 50% Auslastung.
Ich habe keine Idee, woran das liegen kann.
Kommentar