Performance von new vs Stack (war: Nekropost in Qt vs Boost)
-
sehr gut

-
Zusätzlich zu der Tatsache, dass new erst suchen muss, kann es in nebenläufigen Anwendungen passieren, dass sich die einzelnen Threads gegenseitig im Weg stehen. Man kann das zwar verhindern, indem man jedem Thread einen eigenen Heap unterjubelt (mehr dazu hier), aber das ist keine ganz schmerzfreie Angelegenheit -- insbesondere, wenn ein Thread in die Lage kommt, Daten aufräumen zu müssen, die ein anderer angefordert hat, was bei geteilten Containern schon mal vorkommen kann.
Auch darf davon ausgegangen werden, dass die Spitze des Stacks bereits im Cache liegt; das dürfte aber nur bei sehr kleinen und extrem kurzlebigen Objekten von größerer Bedeutung sein. Spannend ist allerdings, dass Objekte, die im selben Zusammenhang angelegt wurden, dann direkt nebeneinander (also cachefreundlich) im Speicher liegen, wenn sie alle auf den Stack gelegt wurden. Kommt man nach längerer Arbeit noch mal auf sie zurück, muss man so nicht für jedes Mini-Objekt einzeln zum Hauptspeicher rausstiefeln.
-
Ich habe genau das Buch auch gelesen, es wird sehr viel mit new und delete gemacht, aber ich glaube es wird nicht gesagt, warum new langsamer ist. Man weiß das es langsamer ist, aber es wird dort nicht explizit erklärt. Jedoch ist das Buch alles in allem sehr Empfehlenswert.
MfG
-
seldon schrieb:
Zusätzlich zu der Tatsache, dass new erst suchen muss, kann es in nebenläufigen Anwendungen passieren, dass sich die einzelnen Threads gegenseitig im Weg stehen. Man kann das zwar verhindern, indem man jedem Thread einen eigenen Heap unterjubelt (mehr dazu hier), aber das ist keine ganz schmerzfreie Angelegenheit -- insbesondere, wenn ein Thread in die Lage kommt, Daten aufräumen zu müssen, die ein anderer angefordert hat, was bei geteilten Containern schon mal vorkommen kann.
Mit modernen Heap-Implementierungen ist das quasi eine "non-issue". Soll heissen: die sind multi-threaded fast so schnell wie ein single-threaded Allokator der keinerlei Locks nimmt.
-
X_2F9 schrieb:
@RHBaum, du meintest "new" ist der Laufzeitperformancekiller schlechthin.
Dass du das nicht verstehst ist kein Problem, die Aussage ist ja auch falsch. Zumindest meine Programme verwenden nicht 90% der Laufzeit für new. ich weiß ja nicht, wie das bei anderen ist, aber wenn ich irgendwo ein Performanceproblem habe, ist das entweder algorithmisch bedingt, oder ich zerschieße mir den prozessorcache durch eine miese Implementierung. New landet dann irgendwo unter Mikrooptimierung.
-
otze schrieb:
Zumindest meine Programme verwenden nicht 90% der Laufzeit für new. ich weiß ja nicht, wie das bei anderen ist, [...]
Nun, gerade Konvertiten von Java (oder anderen VM Sprachen) nach C++ machen oft genau den Fehler alles über den Heap zu allozieren. Wenn man mit C/C++ (oder Pascal, Modula, ...) groß geworden ist, mag das in Fleisch und Blut über gegangen sein, aber die jüngeren unter uns kennen oftmals nur pure Heap oder non-Heap.
-
Die regel ist eigentlich ganz einfach: statisch ist schneller als dynamisch. Das gilt für alle Bereiche der Computertechnik. Und New nutze ich (nur), wenn ich dynamisches Verhalten benötige.
Wir müssen hier auf Arbeit viel mit den IBM-Mainframes kooperieren. Die Mainframe-Programme sind sau schnell. Aber auch nur deshalb, weil die COBOL-Programmierer darauf keine dynamischen Konstrukte nutzen dürfen. Bei denen hat z.B. ein String immer eine fest definierte Länge. Da gibt es keine Toleranz!
Tip: Benutze new nur dann, wenn die statische Variante (Stackobjekt) nicht die Anforderung erfüllt.
-
hustbaer schrieb:
seldon schrieb:
Zusätzlich zu der Tatsache, dass new erst suchen muss, kann es in nebenläufigen Anwendungen passieren, dass sich die einzelnen Threads gegenseitig im Weg stehen. Man kann das zwar verhindern, indem man jedem Thread einen eigenen Heap unterjubelt (mehr dazu hier), aber das ist keine ganz schmerzfreie Angelegenheit -- insbesondere, wenn ein Thread in die Lage kommt, Daten aufräumen zu müssen, die ein anderer angefordert hat, was bei geteilten Containern schon mal vorkommen kann.
Mit modernen Heap-Implementierungen ist das quasi eine "non-issue". Soll heissen: die sind multi-threaded fast so schnell wie ein single-threaded Allokator der keinerlei Locks nimmt.
In Anbetracht der Tatsache, dass der Artikel, den ich verlinkt habe, aus dem Jahr 2010 stammt und Messungen enthält, die das genaue Gegenteil belegen, muss sich da in den letzten zwei Jahren ja viel getan haben.
Sarkasmus mal beiseite, es ist stumpf nicht wahr, dass gängige Heaps mit Multithreading gut zusammenarbeiteten. Wenn du Speicher von einem Heap anforderst oder welchen freigibst, wird er dafür gelockt, und dann müssen die Threads halt aufeinander warten. Die Kosten der Kontextswitcherei sind da noch das kleinere Problem.
Die Größe des Problems nimmt natürlich mit der Anzahl der Threads und der Anzahl der Heap-Allokationen pro Thread zu -- bei zwei Threads muss man schon sehr viel auf dem Heap herumfuhrwerken, um Probleme zu kriegen, aber wenn man mit zwanzig rechnen muss, kann (wird) einem so was böse auf die Performance schlagen.
-
Lock-free Allokator ftw

-
modern != mainstream
-
seldon schrieb:
hustbaer schrieb:
Mit modernen Heap-Implementierungen ist das quasi eine "non-issue". Soll heissen: die sind multi-threaded fast so schnell wie ein single-threaded Allokator der keinerlei Locks nimmt.
In Anbetracht der Tatsache, dass der Artikel, den ich verlinkt habe, aus dem Jahr 2010 stammt und Messungen enthält, die das genaue Gegenteil belegen, muss sich da in den letzten zwei Jahren ja viel getan haben.
Der Artikel belegt gar nix, da steht nichtmal dabei mit welchem OS/welcher CRT sie getestet haben.
Abstract
Allocating memory from the system heap can be an expensive operation due to a lock used by system runtime libraries to synchronize access to the heap. Contention on this lock can limit the performance benefits from multithreading. To solve this problem, apply an allocation strategy that avoids using shared locks, or use third party heap managers.
Wenn ich das schon lese, oh Mann... das ist einfach nicht mehr wahr. OK, wenn ich ein 10 Jahre altes OS einsetze, oder absichtlich Vergleiche mit ausgesucht schlechten Runtime Implementierungen mache.
Ich würde sogar soweit gehen zu behaupten dass es volle Absicht ist dass hier keinerlei Abgaben zu finden sind um was für ein System es sich handelt, und das ganze bloss gequirltes Marketing-Blabla ist.----
Lies mal da, das ist etwas interessanter (guck auf Seite 8 oben wenn du gleich die Charts sehen willst):
http://people.cs.umass.edu/~emery/pubs/berger-oopsla2002.pdfBTW: das was da als "Win32" angeschrieben ist, ist der Windows XP Allokator, und der ist bekanntlich nicht so krass schnell. Spätestens ab SP3, und wenn man den LFH aktiviert (was leider nicht Default ist), sieht es dann viel besser aus.
Oder guck dir an wie nedmalloc skaliert:
http://www.nedprod.com/programs/portable/nedmalloc/ (der erste Chart rechts)Wenn du Speicher von einem Heap anforderst oder welchen freigibst, wird er dafür gelockt, und dann müssen die Threads halt aufeinander warten. Die Kosten der Kontextswitcherei sind da noch das kleinere Problem.
Nein, um Himmels Willen, wie kommst du nur auf sowas?
Lies bitte die Beschreibung von tcmalloc, da steht recht gut beschrieben wie das geht:
http://goog-perftools.sourceforge.net/doc/tcmalloc.html
Und tcmalloc ist ALT.
Mittlerweile kann da quasi jedes OS mithalten was aktuell ausgeliefert wird. Sei's nun Windows 7 oder Mac OS/iOS/*BSD oder auch diverse Linuxe.
(Bzw. nicht nur mithalten, sondern tcmalloc in vielen Anwendungen auch ordentlich abhängen)
-
Kellerautomat schrieb:
Lock-free Allokator ftw

Genaugenommen ist an den schnellen Allokatoren nix "Lock-free" im klassischen Sinne.
Damit meine ich: die haben *keine* "Lock-free" Datenstrukturen, dafür aber sehrwohl klassische Locks, die sie auch ganz klassisch locken. Bloss dass sie per-Thread Free-Lists verwenden (Stichwort "Tread Cache"), und wenn sie mal ein Lock holen müssen gleich viel auf einmal erledigen.
Dadurch sinkt der Anteil der Allokationen die locken müssen soweit, dass es im Idealfall kaum ins Gewicht fällt.