Registriert seit: 19. Mär 2012
Ort: Bochum-Linden
64 Beiträge
Delphi 12 Athens
|
AW: MemoryLeaks mit s := I.ToString
8. Nov 2014, 19:57
VORSICHT: Wenn die Fiberumschaltung irgendwo in einer aufgerufenen Methode vor dem finally geschieht, und der Fiber dann beendet wird, wird finally niemals aufgerufen. Dieses Problem hat man auch beim Thread, wenn er mit Suspend angehalten und dann verworfen wird.
Allgemein: Die erste Entscheidung bei paralleler Programmierung ist, ob man dadurch einen Performancegewinn oder deutlich besser trennbaren Code haben will. Beides ist leider nur selten möglich.
Ob Threads, Fiber oder einfach parallele Abläufe durch geschicktes orthogonales Coding muss sorgfältig abgewägt werden.
Threads machen z.B. Sinn, wenn durch den Einsatz mehrere CPUs echte Parallelität gewährleistet wird, z.B beim Suchen eines Elementes in einer unsortierten riesigen Liste. Einfach nur mehrere Threads aufmachen reicht aber auch da nicht. Das Betriebssystem könnte nämlich mehrere oder sogar alle Threads in einer CPU laufen lassen. Dann wirds sogar deutlich langsamer als eine Iteration über alle Elemente in einem Thread. Die Umschaltung eines Threads ist nicht deterministisch und kostet inkl. der internen völlig intransparenten Optimierung des Betriebssystems 1..100µs. Bei Threads vergisst man gerne, dass das Betriebssystem jeden Thread nicht nur umschaltet, sondern dass die CPU-Ressourcen für die verdeckte interne Optimierung mit steigender Anzahl überproportional ansteigt. Und selbst ein Assemblerbefehl wie ein normales Increment einer Speicherstelle MUSS synchronisiert werden, wenn auch andere Threads darauf zugreifen können. Es gibt aber vier intrinsische Atomic-Assemblerbefehle, die auch in Delphi zur Verfügung stehen.
Fazit: Mehr Threads als CPUs machen NUR für besser trennbaren Code Sinn. Die Performance wird nämlich je zusätzlichem Thread (mehr als CPUs) zwangsläufig immer schlechter. Das ist leider, bis auf ganz wenig Ausnahmen, allgemeingültig. Wenn möglich, ist klassisches Pollen eben fast immer wesentlich schneller als komplexe Strukturen.
Und genau da werden Fiber spannend. Die machen nämlich Sinn, wenn die Laufzeit des Codes bis zur nächsten notwendigen Umschaltung kurz ist, und man davon viele (gerne auch mehrere 1.000) hat. Die Umschaltung eines Fiber ist mit unter 50ns ca. 20..2.000 mal schneller als beim Thread. Wenn man also viele Objekte oder Methoden hat, die alle parallel etwas tun müssen, und man auch keine Verriegelung untereinander im Code haben darf oder nicht möchte, dann machen Fiber absolut Sinn. Threads wären da viel zu langsam, viel zu aufwändig und auch viel zu fehleranfällig.
Eigenes geschicktes Coding ist die schnellste Variante, birgt aber den Nachteil, diese Tools, die man dafür benötigt, immer zu pflegen, und an die neuen Compiler anzupassen. Und da kein Dispatcher (Stackumschaltung) vorhanden ist, sieht der Code zwangsweise an manchen Stellen einfach etwas unübersichtlich aus. Diese Variante habe ich erfolgreich seit über 10 Jahren weltweit in vielen Anlagen (365x24) im Einsatz. Da diese Projekte aber immer komplexer werden, möchte ich nun besser lesbaren und wartbaren Code in den parallelen Prozessen haben. Das sind im Moment meine Entscheidungsprobleme.
Peter Kaisler Das einzig Komplizierte ist zu begreifen wie einfach es ist.
|