PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Warum Java langsam ist.


ethrandil
2004-06-02, 16:29:12
Hallo,
ich möchte hier einfach mal fundierte Quellen sammeln, die sich mit der Geschwindigkeit von Java in allen Bereichen außeinander setzen.

einer kommt schon von Capt'N Coax:
http://www.idiom.com/~zilla/Computer/javaCbenchmark.html

Bitte kein rumflamen. Alles fundiert bitte. Erfahrung zählt nicht.

Danke.

- Eth

Gast
2004-06-02, 16:45:19
Naja. Fundierte Messungen werden immer die eine oder andere Sprache als schneller ermitteln. In bestimmten Bereichen ist Java sicher schneller, als man allgemein vermutet. Allerdings ist mir auch jetzt auch keine zeitkritische Applikation (z.B. Betriebssystem, 3D-Computerspiel) bekannt, die in Java geschrieben wäre.

Selbst der Godfather des Java schreibt in Java in a Nutshell vom Faktor 20, den Javaprogramme teilweise langsamer seien als andere.

ethrandil
2004-06-02, 16:47:07
Ich weiß, dass es je nach Benchmark mal so, mal so ausgehen wird.

Aus diesem grund möchte ich ja auch möglichst viele Benchmarks und Artikel lesen, um mir meine Meinung zu bilden.

- Eth

Gast
2004-06-02, 16:50:13
http://www.kano.net/javabench/
http://web.informatik.uni-bonn.de/II/ag-klein/people/zach/benchmarks/java-vs-c++.html
http://www.javaperformancetuning.com/news/qotm028.shtml
http://www.epcc.ed.ac.uk/javagrande/links.html
http://jeanpaul.lefevre.free.fr/java/cxx.html

Das sollte erstmal reichen. ;)

Trap
2004-06-02, 20:24:43
Java muss garnicht langsam sein, es gibt genug andere Gründe es nicht zu benutzen.

http://page.mi.fu-berlin.de/~prechelt/Biblio/jccpprt_computer2000.pdf
http://www.flownet.com/gat/papers/lisp-java.pdf

pajofego
2004-06-02, 20:47:22
Leider nicht online :-(, aber für diejenigen, die diese Ausgaben haben sehr interessant! Zumal hier Delphi mit von der Partie ist.

1. Arne Schäpers, Rudolf Huttary (hos)
Daniel Düsentrieb
C#, Java, C++ und Delphi im Effizienztest, Teil 2
Know-how,.NET-Corner,Benchmark, ListList, ListList_OOP, objektverarbeitende Programmierung, Compiler, Optimierung, Konstruktoren
c't 21/03, Seite 222

2. Arne Schäpers, Rudolf Huttary (hos)
Daniel Düsentrieb
C#, Java, C++ und Delphi im Effizienztest, Teil 1
Know-how,.NET-Corner,Benchmark, Geschwindigkeitsvergleich, Schleifen, Integer-Arithmetik
c't 19/03, Seite 204

Gruss pajofego

EgonOlsen
2004-06-02, 23:50:52
Allerdings ist mir auch jetzt auch keine zeitkritische Applikation (z.B. Betriebssystem, 3D-Computerspiel) bekannt, die in Java geschrieben wäre.
[/SIZE]Gibt auch nicht sehr viele...IL2 war zu großen Teilen in Java, allerdings 1.1. Chrome benutzt es immerhin fürs Skripting und irgendein Spiel mit Anwälten/Polizisten oder so (Name leider vergessen) war komplett mit Java3D gemacht. Ansonsten sieht das hier sehr nett aus (aber noch keine Beta draußen): http://oddlabs.com/ und AlienFlux ist auch gut geworden (http://www.puppygames.net). Das ist zwar nicht wirklich 3D, aber naja...
Und dann gibt es noch meine Versuche in dieser Richtung und zwar als Webstart-App. hier: http://www.jpct.net/webstart/demo4.jnlp (mit 'x' kann man zwischen Software und OpenGL umschalten, das Fenster im Software-Modus lässt sich skalieren)
Für viele Dinge ist Java IMHO mittlerweile schnell genug.

Edit: Bei einigen der weiter oben im Thread aufgeführten Benchmarks werden z.T. VMs aus der Steinzeit verwendet...also mit Vorsicht geniessen. Wer sich nicht sicher ist, wie schnell/langsam Java ist und ob es ausreicht, sollte es IMO einfach probieren.

pajofego
2004-06-03, 10:09:24
Wer sich nicht sicher ist, wie schnell/langsam Java ist und ob es ausreicht, sollte es IMO einfach probieren.

...oder nimmt sich den Test in der c't vor! Ist relativ aktuell (ende letzten Jahres).

Gast
2004-06-11, 13:30:06
[SIZE=1]Original geschrieben von EgonOlsen
Gibt auch nicht sehr viele...IL2 war zu großen Teilen in Java, allerdings 1.1. Chrome benutzt es immerhin fürs Skripting und irgendein Spiel mit Anwälten/Polizisten oder so (Name leider vergessen) war komplett mit Java3D gemacht.

Das war entweder dieses "Crime Scene Investigation" oder "Law & Order".

EgonOlsen
2004-06-11, 17:01:19
Original geschrieben von Gast
Das war entweder dieses "Crime Scene Investigation" oder "Law & Order". Genau. Law & Order wars.

tb
2004-06-11, 17:19:20
die roten Resultate bitte nicht beachten:
http://www.tommti-systems.de/main-Dateien/reviews/languages/benchmarks.html

Man beachte die verschiedenen VM's (Client, Server, native kompiliert).

Thomas

HellHorse
2004-06-11, 17:57:03
Original geschrieben von tb
die roten Resultate bitte nicht beachten:
http://www.tommti-systems.de/main-Dateien/reviews/languages/benchmarks.html

Man beachte die verschiedenen VM's (Client, Server, native kompiliert).

Thomas
startTime = (new Date()).getTime();
:stareup:

Ok, der Typ hat wirklich nicht so viel Erfahrung mit Java. Initialisiert man z.B. den StringBuilder mit der korrekten Grösse und nicht 60% zu gross fallen bei mir die Zeiten von.
985ms nach 859ms (client vm)
bzw
890ms nach 641ms (server vm)
Mal sehen, was sich sonst noch ändern lässt.
NIO irgendwer :D


Ach ja, wenn man bei C++ die Compileroptimierung reinhaut, wäre es vielleicht fair, das auch bei Java zu tun, auch wenn's nur eine Hand voll Millisekunden schneller läuft.


NIO Zahlen entfernt, da sie nicht korrekt zu sein scheinen.

HellHorse
2004-06-16, 00:04:22
http://kano.net/javabench/

tb
2004-06-16, 00:31:13
Original geschrieben von HellHorse
startTime = (new Date()).getTime();
:stareup:

Ok, der Typ hat wirklich nicht so viel Erfahrung mit Java. Initialisiert man z.B. den StringBuilder mit der korrekten Grösse und nicht 60% zu gross fallen bei mir die Zeiten von.
985ms nach 859ms (client vm)
bzw
890ms nach 641ms (server vm)
Mal sehen, was sich sonst noch ändern lässt.
NIO irgendwer :D


Ach ja, wenn man bei C++ die Compileroptimierung reinhaut, wäre es vielleicht fair, das auch bei Java zu tun, auch wenn's nur eine Hand voll Millisekunden schneller läuft.


NIO Zahlen entfernt, da sie nicht korrekt zu sein scheinen.


Dann musst Du die Größe aber auch bei C++ und C# ändern, es ging bei dem Test nicht um die erforderliche Größe, sondern um das Thema Speicherallokation....

Thomas

HellHorse
2004-06-16, 09:21:02
Original geschrieben von tb
es ging bei dem Test nicht um die erforderliche Größe, sondern um das Thema Speicherallokation....

Und ich dachte es ging um Stringkonkatenation.

Falls es aber wirklich um Speicherallokation gehen sollte, stellt sich die Frage, warum man in C# und Java nicht einfach bloss ein Array alloziert und in das rein schreibt wie in C++ auch.

tb
2004-06-16, 15:28:50
Ich bin der Meinung, der StringBuilder bei C# und Java macht nicht viel mehr, ob man da mit einem Array schneller wäre, bezweifle ich. So schlecht schlägt sich Java nicht, ausser bei den "nested loops" und den "trig. math" kann ich da wirklich nicht meckern. Dagegen muss Microsoft bei C# wohl noch ein wenig optimieren.

Der Titel des Thread's ist ein wenig unglücklich gewählt. Er sollte vielmehr lauten: "Ist Java langsam?"
Ich würde sagen Java und C# sind in 90% der Fälle nicht merklich hinter C++ zurück. Man sollte vielleicht auch mal den Entwicklungskomfort/Entwicklungszeit betrachten, da seh ich C# / Java weit vor C++....

Thomas

grakaman
2004-06-16, 15:47:26
Original geschrieben von tb
Ich bin der Meinung, der StringBuilder bei C# und Java macht nicht viel mehr, ob man da mit einem Array schneller wäre, bezweifle ich. So schlecht schlägt sich Java nicht, ausser bei den "nested loops" und den "trig. math" kann ich da wirklich nicht meckern. Dagegen muss Microsoft bei C# wohl noch ein wenig optimieren.


Der StringBuilder allokiert aber dynamisch den Speicher. Bei einem String Objekt wird für jede weitere Stringoperation ein neues Objekt allokiert. Somit steigt btw der Speicherverbrauch auch temporär viel mehr. Im folgenden Video wird der .NET CLR Profiler gerade an diesem Beispiel demonstriert:

http://msdn.microsoft.com/msdntv/episode.aspx?xml=episodes/en/20030729CLRGN/manifest.xml

MfG

tb
2004-06-16, 15:54:46
Ich denke gelesen zu habem, dass der StringBuilder nix dyn. allokiert, warum initalisiere ich ihn sonst mit "new StringBuilder( Speichergröße );" und bekomm ne Exception, wenn ich die Speichergröße überschreite?

Thomas

grakaman
2004-06-16, 16:16:43
Original geschrieben von tb
Ich denke gelesen zu habem, dass der StringBuilder nix dyn. allokiert, warum initalisiere ich ihn sonst mit "new StringBuilder( Speichergröße );" und bekomm ne Exception, wenn ich die Speichergröße überschreite?

Thomas

So steht es aber in der SDK Doku. Vielleicht überschreitest du ja MaxCapacity, was die Exception hervorruft.

tb
2004-06-16, 16:53:10
"Implementation-specific default values are used if no capacity or maximum capacity is specified when an instance of StringBuilder is initialized.

Notes to Implementers: The default capacity for this implementation is 16, and the default maximum capacity is Int32.MaxValue.

A StringBuilder can allocate more memory as needed to store characters when the value of an instance is enlarged, and the capacity is adjusted accordingly"

Da der StringBuilder jedoch schon wesentlich mehr Speicher reserviert (8*N) hat, als benötigt (1*N), dürfte kein dyn. Anpassung erfolgen.

Thomas

grakaman
2004-06-16, 17:01:19
Original geschrieben von tb
"Implementation-specific default values are used if no capacity or maximum capacity is specified when an instance of StringBuilder is initialized.

Notes to Implementers: The default capacity for this implementation is 16, and the default maximum capacity is Int32.MaxValue.

A StringBuilder can allocate more memory as needed to store characters when the value of an instance is enlarged, and the capacity is adjusted accordingly"

Da der StringBuilder jedoch schon wesentlich mehr Speicher reserviert (8*N) hat, als benötigt (1*N), dürfte kein dyn. Anpassung erfolgen.

Thomas

Du quotest es doch selber


A StringBuilder can allocate more memory as needed to store characters when the value of an instance is enlarged, and the capacity is adjusted accordingly


Warum er bei dir eine Exception bringt, kann ich dir jetzt nicht sagen. Ich kann es auch nicht nachvollziehen, poste doch mal den Code. Auf jeden Fall allokiert er bei Bedarf mehr speicher. Und schaue dir bitte das Video an, auf welches ich oben verlinkt habe. In dem Bsp. waren es zeitliche Unterschiede von spürbaren 2 Sekunden, wenn ich mich recht erinnere.

MfG

tb
2004-06-16, 18:08:13
Original geschrieben von grakaman
Du quotest es doch selber



Warum er bei dir eine Exception bringt, kann ich dir jetzt nicht sagen. Ich kann es auch nicht nachvollziehen, poste doch mal den Code. Auf jeden Fall allokiert er bei Bedarf mehr speicher. Und schaue dir bitte das Video an, auf welches ich oben verlinkt habe. In dem Bsp. waren es zeitliche Unterschiede von spürbaren 2 Sekunden, wenn ich mich recht erinnere.

MfG

Den Fehler hab ich gefunden, war doch was anderes.
Der wichtige Punkt beim StringBuilder ist:
"A StringBuilder can allocate" - Wenn der vorher reservierte Speicher nicht ausreicht, dann holt er sich welchen. Da im Benchmark jedoch wesentlich mehr Speicher reserviert wurde als benötigt, wird nichts dyn. allokiert. Darin liegt ja auch der Vorteil des StringBuilders, im Gegensatz zum simplen String+String ....

Thomas

HellHorse
2004-06-16, 19:24:14
Original geschrieben von tb
Ich bin der Meinung, der StringBuilder bei C# und Java macht nicht viel mehr, ob man da mit einem Array schneller wäre, bezweifle ich.
Warum vergleichst du nicht einfach Gleiches mit Gleichem?
Ja, Schlussendlich ist das Prinzip das gleiche, es wird ein riesen grosses Array alloziert, und Werte von einem kleineren reinkopiert.
Dazwischen sind in Java (vermutlich auch in C#) diverse Methodenaufrufe, in C++ nicht.
Also solltest du aus meiner Sicht entweder einen StringBuilder/Buffer in C++ implementieren oder in C# und Java bloss das rumkopieren machen (und dann den Test umbenennen).

Und wenn es nur um Allokation geht, wieso nicht bloss allozieren, sondern auch kopieren?
Oder warum nicht gleich 10'000 Objekte allozieren, da sich ja all diese Sprachen als OO ausgeben?


Der Test ist noch aus einem weiteren Grund nicht sauber.
In C++ ist ein char 8 bit grosser Integer. In Java verhält sich ein char wie ein 16 bit Integer, ist aber als 32 bit Integer implementiert (soll schneller sein). Du alloziertst also in einem Test, der die Speicherallokation testen soll, in einer Sprache 4 mal so viel Speicher wie in einer anderen. Wies in C# aussieht weiss ich nicht.
Und um wirklich genau das Gleiche zu machen, müsstest du ein C++ eine Arrayimplementation mit rangecheck verwenden.

tb
2004-06-16, 19:42:23
Das man die Benchmarks besser machen kann, sollte anhand der Oberflächlichkeit dieser klar sein.
Am Ende hängt es von der Aufgabenstellung + Systemumgebung ab, welche Sprache / Tools man verwendet, nicht von synthetischen Benchmarks... Auch hat der Programmierer, meiner Meinung nach, einen größeren Einfluß, als die Wahl zwischen Java, C# oder C++.

In diesem Sinne, fröhliches Entwickeln...

http://java.sun.com/j2se/1.5.0/snapshots/

Thomas

Senior Sanchez
2004-06-16, 21:23:53
So, auch mal nen paar Beiträge, die sind ganz besonders interessant:

Java schneller als C/C++?
http://www.symlink.ch/articles/04/06/16/0551250.shtml

und nen Quake 2 Port nach java mit Benchmarkresultaten... zwar noch nicht so schnell wie die C-Version aber schon ordentlich.

http://www.symlink.ch/articles/04/06/15/1520213.shtml

grakaman
2004-06-16, 22:27:33
Original geschrieben von tb
Da im Benchmark jedoch wesentlich mehr Speicher reserviert wurde als benötigt, wird nichts dyn. allokiert. Darin liegt ja auch der Vorteil des StringBuilders, im Gegensatz zum simplen String+String ....

Thomas

Ich kenne den Benchmark nicht, deswegen kann ich dazu nichts sagen. Der Vorteil liegt beim StringBuilder meiner Meinung nach darin, dass weniger Speicher verbraucht wird, weil er eben die Instanz dynamisch verwalten kann.
Bsp:

string a = "a";
a += "b";

Bis der GC zuschlägt, hast du nun zwei Objekte im Speicher. Einmal ein Objekt, was "ab" enthält und dann das alte Objekt mit "a". Selbst wenn du von einem String Objekt, Zeichen löschst und quasie weniger Speicher verbrauchen würdest, wird immer wieder eine neue Instanz erstellt. Und solange der GC nicht zuschlägt, wird sinnlos Speicher verbraten.
Bei intensiveren String Operationen macht sich das deutlich bemerktbar (ich verweise hier immer wieder auf das Video).

MfG

tb
2004-06-16, 23:05:13
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/vbnstrcatn.asp

Der StringBuilder erzeug solange keine neue Instanz, solange der reservierte Speicher ausreicht. Wenn dieser nicht mehr reicht, wird eine neue Instanz mit mehr Speicher gebildet, wie beim normalen String+String. Dies spart Speicherallokationszugriffe + Objektinstanzierungen, also CPU Zeit. Das der GC nicht so oft was zu tun hat, hilft der CPU auch noch. Der StringBuilder arbeitet am besten, wenn er mit dem max. benötigtem Speicher instanziert wird, da so keine neuen Instanzen gebildet werden müssen, was aber nicht immer die geringste Speicherauslastung zu Folge hat.

public StringBuilder()

The string value of this instance is set to String.Empty, and the capacity is set to the implementation-specific default capacity.

public StringBuilder(int capacity)

The string value of this instance is set to String.Empty. If capacity is zero, the implementation-specific default capacity is used.

P.S. Noch was zum Video, die 504 MB vs. 2.2 MB beziehen sich nicht auf die Speicherauslastung, sondern es handelt sich um die Addition aller Speicherreservierungen im Leben der App.

Thomas

grakaman
2004-06-17, 12:06:15
Original geschrieben von tb
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/vbnstrcatn.asp

Der StringBuilder erzeug solange keine neue Instanz, solange der reservierte Speicher ausreicht. Wenn dieser nicht mehr reicht, wird eine neue Instanz mit mehr Speicher gebildet, wie beim normalen String+String. Dies spart Speicherallokationszugriffe + Objektinstanzierungen, also CPU Zeit. Das der GC nicht so oft was zu tun hat, hilft der CPU auch noch. Der StringBuilder arbeitet am besten, wenn er mit dem max. benötigtem Speicher instanziert wird, da so keine neuen Instanzen gebildet werden müssen, was aber nicht immer die geringste Speicherauslastung zu Folge hat.


Da hast du schon recht, die Speichervergrößerung erfolgt quasie Etappenweise. Aber trotzdem wird dann kein neues StringBuilder Objekt erstellt, sondern es bleibt ein und die selbe StringBuilder Instanz, die dann bei Bedarf intern einen größeren Buffer erstellt.
Ich habe einmal das StringBuilder Objekt mit 1 als Capacity initialisiert und 50000 mal die aktuelle Zeit angefügt. Der CLR Profiler zeigt bei der Allokations-Zeittabelle aber selbst hier nur ein allokiertes StringBuilder Objekt. bei den zuletzt allokierten Objekten handelt es sich um String Objekte. Diese werden laut Profiler von einer Factory Klasse, GetStringForStringBuilder geliefert, der das StringBuilder Objekt dann die benötigte Größe übergibt.


P.S. Noch was zum Video, die 504 MB vs. 2.2 MB beziehen sich nicht auf die Speicherauslastung, sondern es handelt sich um die Addition aller Speicherreservierungen im Leben der App.


Naja, das habe ich ja auch nicht behauptet, sondern dass das Video deutlich zeigt, dass der Performance-Unterschied im Sekundenbereich liegt. Trotzdem liegt der temporäre Spcherverbrauch in der Praxis höher, wegen dem GC.

tb
2004-06-18, 20:02:27
Original geschrieben von HellHorse

Der Test ist noch aus einem weiteren Grund nicht sauber.
In C++ ist ein char 8 bit grosser Integer. In Java verhält sich ein char wie ein 16 bit Integer, ist aber als 32 bit Integer implementiert (soll schneller sein). Du alloziertst also in einem Test, der die Speicherallokation testen soll, in einer Sprache 4 mal so viel Speicher wie in einer anderen. Wies in C# aussieht weiss ich nicht.
Und um wirklich genau das Gleiche zu machen, müsstest du ein C++ eine Arrayimplementation mit rangecheck verwenden.


Der C++ Test verwendet wchar_t, welches 16 Bit groß ist. In C# ist ein char ebenfalls 16 Bit groß. Also haben alle Sprachen die gleichen Ausgangsbedingungen. Was die VM noch so alles treibt/knvertiert, ist ein Sun-VM Problem, da kann man als Entwickler nichts machen, wenn man 16 Bit chars will...

Um wirklich einen 100% gleichen Benchmark ablaufen zu lassen, müssten C++, C# und Java den gleichen Source Code verwenden, halt jeweils nur in Java, C# oder C++ übersetzt. Dies ist aber praxisfern, da man so bei Null beginnen müssten und möglichst die Finger von allem bereits impl. Klassen (in Java, C# und C++) lassen müsste.