Wäre Java schneller mit anderer Speicherverwaltung?
-
Gibt's eigentlich irgendwo realistische Benchmarks z.B. "generational GC" vs. "traditional malloc/free"? Schnelle Implementierung von beiden vorausgesetzt, und ein Testprogramm welches dazu führt dass der GC mehrfach laufen muss?
"Idioten-Benchmarks" hab' ich schon einige gesehen - bloss wenn man z.B. so wenig Speicher anfordert dass der GC erst garnie losläuft ist es kein Wunder wenn die GC Version schneller ist. Oder wenn man einen auf Geschwindigkeit getrimmten GC mit der MSVC malloc/free Implementierung vergleicht... naja, auch kein Wunder dass der GC besser abschneidet als "die wohl langsamste malloc/free Implementierung der Welt".
-
Ich sagte Schnell ist relativ, Aufwendige berechnung algorithmen arbeiten im normalfall mit dem physikalischen Speicher. Da lässt sich in C/C++ einfach mehr performance rausholen...
-
hustbaer schrieb:
"Idioten-Benchmarks" hab' ich schon einige gesehen - bloss wenn man z.B. so wenig Speicher anfordert dass der GC erst garnie losläuft ist es kein Wunder wenn die GC Version schneller ist. Oder wenn man einen auf Geschwindigkeit getrimmten GC mit der MSVC malloc/free Implementierung vergleicht... naja, auch kein Wunder dass der GC besser abschneidet als "die wohl langsamste malloc/free Implementierung der Welt".
Gab hier vor Jahren mal einen Test wo C++ gnadenlos abgestunken hat, dann etwas später (glaub 1-2Jahre) hatte Volkard eine C++ Variante vorgestellt welche Java deutlich überlegen war. Der Grund warum es so lange ging: Volkard hatte erst dort das Wissen dazu, damit solltet ihr eine Vorstellung haben wie aufwendig es war in C++ eine effizientere Speicherverwaltung zu realisieren wie die JVM hat(te).
Vielleicht existiert der Thread ja noch, falls ja bitte hier verlinken, würd ihn auch gerne nochmals lesen.
-
rapso schrieb:
yoomoonoo schrieb:
Wäre Java viel schneller, wenn es keinen GC gäbe, aber man dafür auch Objekte auf dem Stack anlegen könnte?
Man sollte aber bedenken dass der sinn von einem GC einfacherere programmierung ist. soeine generische loesung wird im schnitt nicht so schnell sein wie eine gut programmierte explizite speicherverwaltung. aber mein 500ps trecker kann auch meinen 400ps ferrari nicht einholen.
Genau so sehe ich das auch. Ich verbringe meine Tage ja auch nicht damit den Compiler vpn C++ zu optimieren, sondern ueberlasse das den Compiler-Entwicklern. In Java mit dem GC ueberlass ich die Speicherverwaltung dem GC und damit den JVM-Entwicklern. Die werden dafuer bezahlt das sie die JVM optimieren, ich werde dafuer bezahlt Anwendungen zu schreiben.
Mal ehrlich, wer hat hier schonmal in C++ sein eigenen Speichermanagment geschrieben und wer davon war damit besser als die jeweilige new/delete/malloc/free Implementierungen des Compilers?
rapso schrieb:
leider hat das ganze ja auch grosse nachteile, geschwindigkeit ist ja nicht gleich geschwindigkeit. eventuell moechtest du kurzzeitig zeitkritische dinge erledigen, eventuell liegt dir etwas an sehr konstanter guter geschwindigkeit mehr als an peak werten etc.
da schlaegt das echte uebel zu, von VM zu VM verhaelt sich das bei Java anders, du hast keinen verlass. es kann sein dass im hintergrund durchgaengig der gc arbeitet, es kann sein dass er in grossen zeitabstaenden einschlaegt. (ein grund weshalb die meisten GC es erlauben explizit 'hints' an die GC zu geben).Das ist doch der Vorteil einer JVM. Man kann je nach Bedarf den GC austauschen ohne das Programm neu uebersetzen zu muessen. Bzw. man tauscht einfach die JVM aus oder liefert eine angepasste mit. Es gibt ja auch Realtime-Java http://java.sun.com/javase/technologies/realtime/
-
DEvent schrieb:
Es gibt ja auch Realtime-Java http://java.sun.com/javase/technologies/realtime/
Immortal memory holds objects without destroying them except when the program ends. This means that objects created in immortal memory must be carefully allocated and managed.
-
Mal ehrlich, wer hat hier schonmal in C++ sein eigenen Speichermanagment geschrieben und wer davon war damit besser als die jeweilige new/delete/malloc/free Implementierungen des Compilers?
Boost. Ich hab mal ne Liste in der viel eingefügt wurde um locker faktor 20 verschnellert, indem ich den boost allokator genommen hab der auf kleine Objekte optimiert ist.
-
übrigens gings anfangs ja auch darum in Java Objekte auf dem Stack anlegen zu können, was ja immer schneller geht als new, weil man nie speicherbereiche suchen oder aufräumen muss.
-
@DEvent:
Du kannst aber einen Allocator wie tcmalloc verwenden, der ordentlich auf Geschwindigkeit optimiert ist. Und einen Allocator wie den vom MSVC (bzw. HeapAlloc/HeapFree) zu übertreffen (was Geschwindigkeit angeht) ist nicht sonderlich schwer.@WasIstSchnell: du bist ja ein ganz Schlauer. Es gibt genug Software die CPU limitiert ist.
Gerade wenn "schön" programmiert wird sind Dinge wie ein guter Optimizer und ein schneller Allocator wichtig.@Wiss0r: Welchen Allocator hat die C++ Variante verwendet? Ohne diese Angabe ist der Hinweis ziemlich wertlos.
-
DEvent schrieb:
Das ist doch der Vorteil einer JVM. Man kann je nach Bedarf den GC austauschen ohne das Programm neu uebersetzen zu muessen.
es ist sicher kein vorteil wenn der entwickler sich nicht auf das laufzeitverhalten eines GC verlassen kann... wie ich schon sagte.
-
Wiss0r schrieb:
Vielleicht existiert der Thread ja noch, falls ja bitte hier verlinken, würd ihn auch gerne nochmals lesen.
http://www.c-plusplus.net/forum/viewtopic-var-t-is-70097-and-start-is-0.html
-
raps schrieb:
DEvent schrieb:
Das ist doch der Vorteil einer JVM. Man kann je nach Bedarf den GC austauschen ohne das Programm neu uebersetzen zu muessen.
es ist sicher kein vorteil wenn der entwickler sich nicht auf das laufzeitverhalten eines GC verlassen kann... wie ich schon sagte.
das ist aber einer der grundsätze, nach denen man in java handeln sollte. der GC kann sonstwie implementiert sein und man sollte sich erstens nicht darauf verlassen, dass er in irgendeiner bestimmten art und weise arbeitet und zweitens sollte man sogar nichtmal versuchen, den GC zu überlisten.
hab mal ein schönes beispiel gesehen, das zeigt, wie sehr man in java auf die nase fallen kann, wenn man versucht, schlauer als der GC zu sein. ging um eine bestimmte variante des object poolings. der code wurde durch pooling in der sun 1.1 jvm geringfügig schneller. mit einer neueren jvm version war der code allerdings um mehr als faktor 10 langsamer, als ein code vollständig ohne pooling.
in java ist ein "new" tatsächlich nichts böses, solange die objekte nur kurz genug existieren.
-
raps schrieb:
DEvent schrieb:
Das ist doch der Vorteil einer JVM. Man kann je nach Bedarf den GC austauschen ohne das Programm neu uebersetzen zu muessen.
es ist sicher kein vorteil wenn der entwickler sich nicht auf das laufzeitverhalten eines GC verlassen kann... wie ich schon sagte.
Doch, denn Java wird wohl zum größten Teil für Business und Enterprise Applications eingesetzt. Dort interessiert man sich idR nicht für das Laufzeitverhalten des GC, weil die Flaschenhälse ganz woanders liegen (meistens bei der Datenbank).
Und wo die Geschwindigkeit des GC nicht ausreichend ist, setzt man halt kein Java ein. Der prozentuale Anteil der Software, wo das der Fall ist, dürfte aber recht gering sein (hardwarenahe Programmierung mal ausgeschlossen).
-
Konfuzius sagt: Ein Weg zu kennen, ist nicht dasselbe wie Ihn zu gehen.
-
hustbaer schrieb:
@Wiss0r: Welchen Allocator hat die C++ Variante verwendet? Ohne diese Angabe ist der Hinweis ziemlich wertlos.
Nö, wieso? Jetzt hat Gregor den Thread verlinkt den ich meinte und du kannst dir alles in Ruhe durchlesen
Danke Gregor!
-
@Wiss0r:
Hm.
Ich kann weder in dem hier verlinkten Thread noch in dem dort wiederum verlinkten Thread jmd. finden der das z.B. mal mit tcmalloc o.ä. probiert hätte.
Dass die Variante mit dem selbstgestrickten small object allocator recht schnell ist ist klar, der verzichtet ja auch darauf new komplett zu ersetzen (=muss mit grössen umgehen können die erst zur Laufzeit bekannt sind), und verzichtet auch auf jegliche thread-sicherheit.Interessant wäre für mich ein Vergleich zwischen einem generischen Allokator ala tcmalloc und GC. Alles andere als einen fertigen, generischen Allokator einzubinden ist meist einfach zuviel Aufwand. Ausgenommen Fälle wo es wirklich extrem viel bringt und schön weggekapselt werden kann -- wenn man z.b. irgendwelche low-level Libraries schreibt.
-
hustbaer schrieb:
@Wiss0r:
Hm.
Ich kann weder in dem hier verlinkten Thread noch in dem dort wiederum verlinkten Thread jmd. finden der das z.B. mal mit tcmalloc o.ä. probiert hätte.
Dass die Variante mit dem selbstgestrickten small object allocator recht schnell ist ist klar, der verzichtet ja auch darauf new komplett zu ersetzen (=muss mit grössen umgehen können die erst zur Laufzeit bekannt sind), und verzichtet auch auf jegliche thread-sicherheit.Interessant wäre für mich ein Vergleich zwischen einem generischen Allokator ala tcmalloc und GC. Alles andere als einen fertigen, generischen Allokator einzubinden ist meist einfach zuviel Aufwand. Ausgenommen Fälle wo es wirklich extrem viel bringt und schön weggekapselt werden kann -- wenn man z.b. irgendwelche low-level Libraries schreibt.
Dafür gibts doch die Boost.Allocators, du weißt in C++ ja wie groß deine Datenstrukturen sind.