Discussion:
Java und Effizienz
(zu alt für eine Antwort)
Ulrich Frank
2006-05-19 08:09:25 UTC
Permalink
Hallo NG,

ich habe eine Frage bzgl. der Effizienz von Java. Und zwar habe ich
gehört, dass Java durchaus mit C oder C++ in Sachen Laufzeit mithalten
kann, solange man nicht mit Objekten arbeitet (also ohne Verwendung des
Heaps). Statt dessen sollte man nur Arrays und Schleifen verwenden (die
Verwendung bezieht sich natürlich auf rechenintensive Aufgaben, die in
Model Klassen erledigt werden sollen, z.B. Parser oder
Matrixmultiplikation. Es ist klar, dass man eine OO Sprache nur
verwenden sollte, wenn man auch mit Objekten arbeiten will. Aber zur
Performanzsteigerung kann man die rechenintensiven Aufgaben optimieren
und den Rest (GUI) mittels OO Konzepten lösen ;)

Meinungen?

Als nächstes dachte ich mir - "musst du mal nachlesen". Ich habe auch
ziemlich viele Seiten gefunden, die teilweise aber leider sehr alt
(beziehen sich auf Java 1.1, 1.2, 1.3) sind und inzwischen ist der Java
Compiler auch so aufgebaut, dass er viele Optimierungen selbst
vornimmt.
Beispiel: Hat man eine for-Schleife "for (int i = 0; i < 10000; i++)
{}" dann habe ich gelesen, dass man in so einem Fall nicht von 0 bis
10000 hoch zählen soll, sondern von 10000 runter bis 0. Warum? Weil
die Abbruchbedingung der Schleife ein Vergleich ist und der Vergleich
mit 0 schneller behandelt wird als der Vergleich mit (hier) 10000.
Also: for (int i = 9999; i >= 0; i--)

Stimmt das? Übernimmt der Compiler so eine Optimierung?

Kennt ihr eine gute (aktuelle, für Java 1.5 sinnvolle Optimierungen)
Site oder ein Buch, in dem dieses Thema behandelt wird?

Danke und Grüße,
Uli
Christoph Jerolimov
2006-05-19 08:24:22 UTC
Permalink
Post by Ulrich Frank
Hallo NG,
ich habe eine Frage bzgl. der Effizienz von Java. Und zwar habe ich
gehört, dass Java durchaus mit C oder C++ in Sachen Laufzeit mithalten
kann, solange man nicht mit Objekten arbeitet (also ohne Verwendung des
Heaps). Statt dessen sollte man nur Arrays und Schleifen verwenden (die
Verwendung bezieht sich natürlich auf rechenintensive Aufgaben, die in
Model Klassen erledigt werden sollen, z.B. Parser oder
Matrixmultiplikation. Es ist klar, dass man eine OO Sprache nur
verwenden sollte, wenn man auch mit Objekten arbeiten will. Aber zur
Performanzsteigerung kann man die rechenintensiven Aufgaben optimieren
und den Rest (GUI) mittels OO Konzepten lösen ;)
Meinungen?
Es ist schwer für eine optimierte Java Lösung an eine optimierte C
Lösung dran zu kommen. Wenn man in beiden aber "einfach nur normalen"
Code schreibt sollte sich das nicht mehr viel geben.
Post by Ulrich Frank
Als nächstes dachte ich mir - "musst du mal nachlesen". Ich habe auch
ziemlich viele Seiten gefunden, die teilweise aber leider sehr alt
(beziehen sich auf Java 1.1, 1.2, 1.3) sind und inzwischen ist der Java
Compiler auch so aufgebaut, dass er viele Optimierungen selbst
vornimmt.
Beispiel: Hat man eine for-Schleife "for (int i = 0; i < 10000; i++)
{}" dann habe ich gelesen, dass man in so einem Fall nicht von 0 bis
10000 hoch zählen soll, sondern von 10000 runter bis 0. Warum? Weil
die Abbruchbedingung der Schleife ein Vergleich ist und der Vergleich
mit 0 schneller behandelt wird als der Vergleich mit (hier) 10000.
Also: for (int i = 9999; i >= 0; i--)
Stimmt das? Übernimmt der Compiler so eine Optimierung?
Nein. Das kann er schlicht nicht, da es eine total andere Bedeutung hat
ob du eine Liste von vorne nach hinten oder von hinten nach vorne
durchgehst. (Genauer gesagt, es könnte zwar das selbe Ergebnis bei
rauskommen, muss aber definitiv nicht.)
Post by Ulrich Frank
Kennt ihr eine gute (aktuelle, für Java 1.5 sinnvolle Optimierungen)
Site oder ein Buch, in dem dieses Thema behandelt wird?
http://www.oreilly.com/catalog/javapt2/ - Ich selbst hab nur drin
geblättert und fand das was ich sah sehr gut. Was ich auch von anderen
bestätigt bekommen habe die es ganz (größten teils) gelesen haben.
Post by Ulrich Frank
Danke und Grüße,
Uli
Gruß Christoph
Michael Klemm
2006-05-19 12:25:34 UTC
Permalink
Post by Christoph Jerolimov
Post by Ulrich Frank
Beispiel: Hat man eine for-Schleife "for (int i = 0; i < 10000; i++)
{}" dann habe ich gelesen, dass man in so einem Fall nicht von 0 bis
10000 hoch zählen soll, sondern von 10000 runter bis 0. Warum? Weil
die Abbruchbedingung der Schleife ein Vergleich ist und der Vergleich
mit 0 schneller behandelt wird als der Vergleich mit (hier) 10000.
Also: for (int i = 9999; i >= 0; i--)
Stimmt das? Übernimmt der Compiler so eine Optimierung?
Nein. Das kann er schlicht nicht, da es eine total andere Bedeutung hat
ob du eine Liste von vorne nach hinten oder von hinten nach vorne
durchgehst. (Genauer gesagt, es könnte zwar das selbe Ergebnis bei
rauskommen, muss aber definitiv nicht.)
Das ist nicht korrekt. Ein optimierender Übersetzer kann die Schleife
durchaus umdrehen. Allerdings muss er dabei nachweisen, dass die
Abhängigkeitsdistanz der Schleife eine Umkehr der Laufrichtung erlaubt.

Es ist also möglich, wenn ein Übersetzer genügend "schlau" ist und eine
entsprechende Analyse im Optimierer eingebaut hat.

Viele Grüße
-michael
--
Post by Christoph Jerolimov
Nenne mir ein Wort und ich erkläre Dir, daß es griechischen Ursprungs
ist
Na dann: Semmelknödel und Wolpertinger
(Anastasios Tsitlakidis und Michael Rauscher in d.c.l.j)
Ingo R. Homann
2006-05-19 08:29:24 UTC
Permalink
Hi,
Post by Ulrich Frank
Hallo NG,
ich habe eine Frage bzgl. der Effizienz von Java....
Na, da packst Du ja ein heisses Eisen an! ;-)
Post by Ulrich Frank
Meinungen?
Als nächstes dachte ich mir - "musst du mal nachlesen". Ich habe auch
ziemlich viele Seiten gefunden, die teilweise aber leider sehr alt
(beziehen sich auf Java 1.1, 1.2, 1.3) sind und inzwischen ist der Java
Compiler auch so aufgebaut, dass er viele Optimierungen selbst
vornimmt.
Beispiel: Hat man eine for-Schleife "for (int i = 0; i < 10000; i++)
{}" dann habe ich gelesen, dass man in so einem Fall nicht von 0 bis
10000 hoch zählen soll, sondern von 10000 runter bis 0. Warum? Weil
die Abbruchbedingung der Schleife ein Vergleich ist und der Vergleich
mit 0 schneller behandelt wird als der Vergleich mit (hier) 10000.
Also: for (int i = 9999; i >= 0; i--)
Stimmt das? Übernimmt der Compiler so eine Optimierung?
In dem konkreten Fall würde der Compiler vermutlich sogar noch besser
optimieren und die Schleife ganz entfernen.

Andernfalls hast Du Recht - zumindest zum Teil: Der Vergleich auf 0 ist
auf einigen Prozessoren schneller, weswegen die "Rückwärts"-Schleife
dort schneller wäre. Auf anderen jedoch nicht.

ABER: Wenn Du mit dem Index auf ein Array zugreifst, kann das
runterzählen mächtig nach hinten losgehen, weil der Level-sonstwas-Cache
im Prozessor, in den immer Teile des Arrays gelegt werden, besser dafür
optimiert ist, fortlaufende Zugriffe zu tätigen.

Und damit sind wir eigentlich auch schon bei den einzigen zuverlässigen
Aussagen über Optimierungen: "premature optimization is evil", "erst
profilen, dann optimieren" und "im Zweifelsfall probieren, testen und
messen". Und das für alle in Frage kommenden Kombinationen von
Hardware/Prozessor, Betriebssystem und JVM. Daher...
Post by Ulrich Frank
Kennt ihr eine gute (aktuelle, für Java 1.5 sinnvolle Optimierungen)
Site oder ein Buch, in dem dieses Thema behandelt wird?
...kann da IMHO auch kein Buch wirklich weiterhelfen. Es kommt so extrem
auf den speziellen Einzelfall an, dass sich generelle
Lowlevel-Optimierungs-Tricks sowieso nicht lohnen (oder wie oben
gezeigt, sogar mächtig nach hinten losgehen)!

Lowlevel-Optimierungen sollte man in 99,999% aller Fälle der JVM überlassen!

Ciao,
Ingo
Michael Paap
2006-05-19 08:41:53 UTC
Permalink
Post by Ulrich Frank
ich habe eine Frage bzgl. der Effizienz von Java. Und zwar habe ich
gehört, dass Java durchaus mit C oder C++ in Sachen Laufzeit mithalten
kann, solange man nicht mit Objekten arbeitet (also ohne Verwendung des
Heaps).
Wo man derlei hören kann, da halte dich fern, außer du magst es, mit
unqualifiziertem Blödsinn abgefüllt zu werden.

Andererseits... wenn du Glück hast, entsteht jetzt ein langer und
lehrreicher Thread, weil es in dclj gute Menschen gibt (keine Ironie!),
die noch im idiotischsten Gebrabbel den wahren Kern suchen.
Post by Ulrich Frank
Kennt ihr eine gute (aktuelle, für Java 1.5 sinnvolle Optimierungen)
Site oder ein Buch, in dem dieses Thema behandelt wird?
Schreibe saubere objektorientierte Anwendungen. Wenn sie schnell genug
für den Anwednungszweck sind, sei glücklich. Wenn nicht, benutze einen
Profiler, um herauszufinden, wo das Problem liegt.

Gruß,
Michael
Stefan Werner
2006-05-19 10:50:29 UTC
Permalink
Post by Michael Paap
Schreibe saubere objektorientierte Anwendungen. Wenn sie schnell genug
für den Anwednungszweck sind, sei glücklich. Wenn nicht, benutze einen
Profiler, um herauszufinden, wo das Problem liegt.
Ein wahres Wort. Ich habe jahrelang und in verschiedenen Sprachen viel
Zeit aufgewendet, möglichst "effizient" zu programmieren, und noch viel
mehr Zeit, um diese ach so effizienten Programme dann wieder an leicht
veränderte Anforderungen anpassen zu können.

Höchstens eines würde ich noch anfügen: Die Entwicklung bzw. Auswahl
eines besseren Algorithmus für ausgewählte zeitkritische Programmteile
wird sehr viel mehr bringen und schneller zum Ziel führen, als die Wahl
einer anderen Programmiersprache oder das Einbauen und Austesten des
letzten Geschwindigkeitskniffs.


-stef
Stefan Waldmann
2006-05-19 14:54:13 UTC
Permalink
Post by Michael Paap
Schreibe saubere objektorientierte Anwendungen. Wenn sie schnell genug
für den Anwednungszweck sind, sei glücklich. Wenn nicht, benutze einen
Profiler, um herauszufinden, wo das Problem liegt.
Soweit stimme ich dir zu. Aber heißt dass nun, dass ich mir fortan
überhaupt keine Gedanken mehr zum Thema Performanz machen muss?

Ein Beispiel:

A)

String s = "";
for (int i=1; i<=100000; i++) {
s += i;
}

VS.

B)

StringBuilder sb = new StringBuilder();
for (int i=1; i<=100000; i++) {
sb.append(i);
}
String s = sb.toString();


Mir geht's jetzt nicht um die Schleife an sich, sondern darum, dass in
Fall A) in jedem Schleifendurchlauf implizit ein StringBuilder angelegt
wird, darauf 2x append() aufgerufen wird (jeweils einmal für s und i),
darauf wieder toString() aufgerufen und das Resultat s zugewiesen wird.
Also 100.000 Instanzen von StringBuilder, die erzeugt und
Garbage-Collected werden müssen, im Gegensatz zu Beispiel B), wo nur
eine Instanz benötigt wird.

Wenn man nun argumentieren würde, dass es egal wäre, welche Version
eingesetzt wird (so könnte deine o.a. Aussage sicherlich ausgelegt
werden), mit welchen Gründen würde man das tun? "Die heutigen Systeme
sind doch so schnell und haben so viel Speicher dass das keine Rolle
spielt." Oder "So etwas wird vom (HotSpot-)Compiler erkannt und
automatisch optimiert". ?? (Meine Argumente an dieser Stelle sind rein
spekulativ)

Was ist mit "Kleinvieh macht auch Mist"? Wenn ich also an vielen Stellen
die weniger performante Version wähle, summiert sich das nicht
irgendwann so sehr, dass man die Auswirkungen letztendlich zu spüren
bekommt?


Gruß
Stefan
--
Programmierer [m], seltener auch ~in [w]:
Irdische, i.a. humanoide Lebensform, die in einem komplizierten
biochemischen Prozess Kaffee, Cola und Pizza in maschinenlesbaren
Programmcode umwandelt.
Ralf Ullrich
2006-05-19 15:27:11 UTC
Permalink
Post by Stefan Waldmann
Post by Michael Paap
Schreibe saubere objektorientierte Anwendungen. Wenn sie schnell genug
für den Anwednungszweck sind, sei glücklich. Wenn nicht, benutze einen
Profiler, um herauszufinden, wo das Problem liegt.
Soweit stimme ich dir zu. Aber heißt dass nun, dass ich mir fortan
überhaupt keine Gedanken mehr zum Thema Performanz machen muss?
Ja.

Du solltest dir aber Gedanken darüber machen trotzdem auf Best Practices
zu achten.
Post by Stefan Waldmann
A)
String s = "";
for (int i=1; i<=100000; i++) {
s += i;
}
Das ist keine Best Practice.
Post by Stefan Waldmann
B)
StringBuilder sb = new StringBuilder();
for (int i=1; i<=100000; i++) {
sb.append(i);
}
String s = sb.toString();
Das schon.
Post by Stefan Waldmann
Wenn man nun argumentieren würde, dass es egal wäre, welche Version
eingesetzt wird (so könnte deine o.a. Aussage sicherlich ausgelegt
werden), mit welchen Gründen würde man das tun?
Man kann so argumentieren, und man würde argumentieren, dass die vom Code
auszuführende Funktion im Vordergrund stehen sollte. D.h. beim Schreiben
des Codes sollte man zu allererst daran denken, dass er korrekt ist. (Und
vielleicht noch, dass diese Korrektheit am Code deutlich erkennbar,
sprich: lesbar, ist
Post by Stefan Waldmann
Was ist mit "Kleinvieh macht auch Mist"? Wenn ich also an vielen Stellen
die weniger performante Version wähle, summiert sich das nicht irgendwann
so sehr, dass man die Auswirkungen letztendlich zu spüren bekommt?
Wenn man fertig ist. Und dann kann man immer noch einen Profiler anwerfen
und ist immer noch produktiver, trotz dieses zusätzlichen Schritts, als
wenn man ständig versucht hätte den _scheinbar_ effizientesten Code zu
entwerfen. Man macht sich nämlich dann mit dem Profiler-Ergebnis genau die
gleichen Optimierungsgedanken, wie sonst auch, aber dann konzentriert auf
die 20% des Codes, bei denen es was bringt.

cu

BTW: für dein Beispiel, könnte in einer Anwendung, die sehr sehr oft
toString() verwendet, ein Refactoring sinnvoll sein, von:

public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(field1);
sb.append(field2);
sb.append(field3);
return sb.toString();
}

zu

interface Appender {
String toString();
void appendTo(Appendable a) throws IOException;
}

// implementing Appender
public final String toString() {
StringBuilder sb = new StringBuilder();
try {
appendTo(sb);
} catch (IOE e) {...}
}

public void appendTo(Appendable a) throws IOException {
((Appender)field1).appendTo(a);
((Appender)field2).appendTo(a);
((Appender)field3).appendTo(a);
}

Ob sich das allerdings lohnt, kann dir _immer_ nur ein Test verraten.
Tendenziell ist die Appender-Lösung schneller, speziell wenn du z.B. aus

System.out.println(myObject);

dann auch konsequent

((Appender)myObject).appendTo(System.out);

machst.

Du kannst anhand von Tests selbst entscheiden, ob sich die
"Source-Code-Obfuscation-By-Optimization" durch Performanzgewinne
rechtfertigt.

(Die Appender-Casts wären im realen Einsatz nicht nötig, und sollen hier
nur andeuten, dass die gecasteten Objekte, das Appender-Interface
implementieren.)
b***@yahoo.de
2006-05-19 16:05:44 UTC
Permalink
wenn man keine objekte verwendet und nur das primitivste , was alle
sprache verwendet, dann braucht man nicht java, und bei allen sprachen
ist es sauschnell.
Andree Yang
Wanja Gayk
2006-05-22 13:06:07 UTC
Permalink
Post by b***@yahoo.de
wenn man keine objekte verwendet und nur das primitivste , was alle
sprache verwendet, dann braucht man nicht java, und bei allen sprachen
ist es sauschnell.
Andree Yang
[Fullquote beabsichtigt]

Mann Andree, jetzt reicht es echt!
Lern _endlich_ ordentlich zu zitieren und auf das passende Posting zu
antworten. Ein wenig Groß-/Kleinschreibung für deine Postings würde sie
sicher auch lesbarer machen.
"berlinhelps2006"? Am Arsch! "berlintrashes2006" passt besser, denn
deine Postings hängen wie Fremdkörper in jedem Diskussionsfaden, meist
außerhalb des Kontexts außerdem postest du gerne doppelt.
Du scheinst dir keinerlei Mühe zu geben, du rotzt deine Postings lieblos
nach übelster "fire & forget" Manier raus, weil es dich scheinbar einen
Scheißdreck interessiert, ob die Newsgroup lesbar bleibt oder nicht.
Dass du des öfteren auf dein Misverhalten aufmerksam gemacht wurdest, es
aber trotzdem beharrlich ignorierst, setzt er Sache noch die Krone auf.

Und nochmal für dich: LESE und BEHERZIGE bitte die folgenden Seiten:
http://einklich.net/usenet/techrules.htm
Speziell:
http://einklich.net/usenet/zitier.htm
http://www.afaik.de/usenet/faq/zitieren/

Der Einsatz eiens passenden Newsreaders kann dir das übrigens wesentlich
vereinfachen. "40tude Dialog" ist dein Freund:
http://www.40tude.com/dialog/

Wie auch immer:
Ich lege jedenfalls keinen Wert mehr dein Zeug zu lesen und werde deine
Postings in Zukunft automatisch ausfiltern.

Wenn du immer weniger Antworten auf deine Beiträge bekommst, sollte dich
das jedenfalls nicht wundern: Es könnte daran liegen, dass es einige
Leute geben wird, die das Ausfiltern still und heimlich tun, ohne es
anzukündigen.

*PLONK!*

diesmal keinen Gruß,
-Wanja-

ps: ja, ich plonke hin und wieder öffentlich, weil ich der felsenfesten
Überzeugung bin, dass man der Scheiße nicht anders beikommen kann. Wer
das nicht lesen will, kann einen Filter auf [PLONK] im Subject setzen.
--
"Gewisse Schriftsteller sagen von ihren Werken immer: 'Mein Buch, mein
Kommentar, meine Geschichte'. [..] Es wäre besser, wenn sie sagten:
'unser Buch, unser Kommentar, unsere Geschichte'; wenn man bedenkt, dass
das Gute darin mehr von anderen ist als von ihnen." [Blaise Pascal]
Stefan Waldmann
2006-05-22 13:42:31 UTC
Permalink
Post by Wanja Gayk
Post by b***@yahoo.de
wenn man keine objekte verwendet und nur das primitivste , was alle
sprache verwendet, dann braucht man nicht java, und bei allen sprachen
ist es sauschnell.
Andree Yang
[Fullquote beabsichtigt]
Mann Andree, jetzt reicht es echt!
Lern _endlich_ ordentlich zu zitieren und auf das passende Posting zu
antworten. Ein wenig Groß-/Kleinschreibung für deine Postings würde sie
sicher auch lesbarer machen.
"berlinhelps2006"? Am Arsch! "berlintrashes2006" passt besser, denn
deine Postings hängen wie Fremdkörper in jedem Diskussionsfaden, meist
außerhalb des Kontexts außerdem postest du gerne doppelt.
Du scheinst dir keinerlei Mühe zu geben, du rotzt deine Postings lieblos
nach übelster "fire & forget" Manier raus, weil es dich scheinbar einen
Scheißdreck interessiert, ob die Newsgroup lesbar bleibt oder nicht.
Dass du des öfteren auf dein Misverhalten aufmerksam gemacht wurdest, es
aber trotzdem beharrlich ignorierst, setzt er Sache noch die Krone auf.
http://einklich.net/usenet/techrules.htm
http://einklich.net/usenet/zitier.htm
http://www.afaik.de/usenet/faq/zitieren/
Endlich spricht mal jemand aus was ich mir auch schon länger denke...!!
Post by Wanja Gayk
Ich lege jedenfalls keinen Wert mehr dein Zeug zu lesen und werde deine
Postings in Zukunft automatisch ausfiltern.
Dito.


Gruß
Stefan
--
Programmierer [m], seltener auch ~in [w]:
Irdische, i.a. humanoide Lebensform, die in einem komplizierten
biochemischen Prozess Kaffee, Cola und Pizza in maschinenlesbaren
Programmcode umwandelt.
b***@yahoo.de
2006-05-19 16:05:46 UTC
Permalink
wenn man keine objekte verwendet und nur das primitivste , was alle
sprache verwendet, dann braucht man nicht java, und bei allen sprachen
ist es sauschnell.
Andree Yang
Stefan Matthias Aust
2006-05-20 07:20:41 UTC
Permalink
Post by Ralf Ullrich
Post by Stefan Waldmann
[...]
Das ist keine Best Practice.
Post by Stefan Waldmann
B)
StringBuilder sb = new StringBuilder();
for (int i=1; i<=100000; i++) {
sb.append(i);
}
String s = sb.toString();
Das schon.
Nun, mal sollte wo immer möglich die Kapazität des Builders angeben. In
diesem konkreten Fall ist es einfach. Ein

StringBuilder b = new StringBuilder(488895);

wäre besser. Auch 500.000 als grober Schätzwert wäre ok. Ohne Kapazität
ist die VM unnötigerweise laufend damit beschäftigt (startend von 16
über 34, 70, 142, 286, 574, 1150, 2302, 4606, 9214, 18430, 36862, 73726,
147454, 294910 bis 589822) den Buffer zu vergrößern.

Mit der Abschätzung 500.000 benötigt das Programm (für den
StringBuilder) 1MB Speicher, ohne Abschätzung mindestens
(294910+589822)*2 = 1,8MB Speicher - nicht gerechnet die Zeit für die
Kopiervorgänge.
Post by Ralf Ullrich
Man kann so argumentieren, und man würde argumentieren, dass die vom
Code auszuführende Funktion im Vordergrund stehen sollte. D.h. beim
Schreiben des Codes sollte man zu allererst daran denken, dass er
korrekt ist. (Und vielleicht noch, dass diese Korrektheit am Code
deutlich erkennbar, sprich: lesbar, ist
Oder:

Make it run, make it right, make it fast, make it small (Kent Beck)
--
Stefan Matthias Aust // Ergo bibamus, ne sitiamus, vas repleamus!
Frank Stolle
2006-05-20 07:53:08 UTC
Permalink
Post by Stefan Matthias Aust
Post by Ralf Ullrich
Post by Stefan Waldmann
[...]
Das ist keine Best Practice.
Post by Stefan Waldmann
B)
StringBuilder sb = new StringBuilder();
for (int i=1; i<=100000; i++) {
sb.append(i);
}
String s = sb.toString();
Das schon.
Nun, mal sollte wo immer möglich die Kapazität des Builders angeben. In
diesem konkreten Fall ist es einfach. Ein
StringBuilder b = new StringBuilder(488895);
wäre besser. Auch 500.000 als grober Schätzwert wäre ok.
Es ist also Best Practise auch schon bei Werten von 100 oder so die
Kapazität mit anzugeben? Und wie Großzügig wird die in der Regel von
euch kalkuliert?

Grüße

Frank
Stefan Matthias Aust
2006-05-20 08:18:28 UTC
Permalink
Post by Frank Stolle
Post by Stefan Matthias Aust
StringBuilder b = new StringBuilder(488895);
wäre besser. Auch 500.000 als grober Schätzwert wäre ok.
Es ist also Best Practise auch schon bei Werten von 100 oder so die
Kapazität mit anzugeben?
Ich mache das, schon damit IDEA nicht rumnervt.
Post by Frank Stolle
Und wie Großzügig wird die in der Regel von euch kalkuliert?
So genau wie möglich. Nehmen wir mal den Fall, du wolltest Musikdateien
laden und verarbeiten. Typischerweise hat ein Track 3-5min Spielzeit und
eine MP3-Datei dann 3-6MB Größe. Also würde ich 6.000.000 als Größe für
ein ByteArrayOutputStream setzen.
--
Stefan Matthias Aust // Ergo bibamus, ne sitiamus, vas repleamus!
Thomas Kellerer
2006-05-20 08:53:51 UTC
Permalink
Post by Stefan Matthias Aust
So genau wie möglich. Nehmen wir mal den Fall, du wolltest Musikdateien
laden und verarbeiten. Typischerweise hat ein Track 3-5min Spielzeit und
eine MP3-Datei dann 3-6MB Größe. Also würde ich 6.000.000 als Größe für
ein ByteArrayOutputStream setzen.
Ich würde mir zuerst mal überlegen, ob es nicht eine Lösung gibt, bei der ich
nicht die gesamten Daten im Speicher halten muß...

Thomas
Stefan Matthias Aust
2006-05-20 09:00:50 UTC
Permalink
Post by Thomas Kellerer
Ich würde mir zuerst mal überlegen, ob es nicht eine Lösung gibt, bei
der ich nicht die gesamten Daten im Speicher halten muß...
Das so eine Lösung nicht existiert hatte ich mal vorausgesetzt :)
--
Stefan Matthias Aust // Ergo bibamus, ne sitiamus, vas repleamus!
Stefan Waldmann
2006-05-20 16:15:14 UTC
Permalink
Post by Stefan Matthias Aust
Post by Ralf Ullrich
Post by Stefan Waldmann
[...]
Das ist keine Best Practice.
Post by Stefan Waldmann
B)
StringBuilder sb = new StringBuilder();
for (int i=1; i<=100000; i++) {
sb.append(i);
}
String s = sb.toString();
Das schon.
Nun, mal sollte wo immer möglich die Kapazität des Builders angeben. In
diesem konkreten Fall ist es einfach. Ein
StringBuilder b = new StringBuilder(488895);
wäre besser.
Ok, ich sehe ein dass mein Beispiel suboptimal war. Mir ging es in
erster Linie darum, den Aspekt mit den vielen kurzlebigen Objekte
herauszuheben. Diesen anderen Aspekt habe ich dann wohl außen vor
gelassen, um nicht zu sagen, übersehen ;-)


Gruß
Stefan
Stefan Waldmann
2006-05-20 16:07:55 UTC
Permalink
Post by Ralf Ullrich
Post by Stefan Waldmann
Post by Michael Paap
Schreibe saubere objektorientierte Anwendungen. Wenn sie schnell genug
für den Anwednungszweck sind, sei glücklich. Wenn nicht, benutze einen
Profiler, um herauszufinden, wo das Problem liegt.
Soweit stimme ich dir zu. Aber heißt dass nun, dass ich mir fortan
überhaupt keine Gedanken mehr zum Thema Performanz machen muss?
Ja.
Du solltest dir aber Gedanken darüber machen trotzdem auf Best Practices
zu achten.
Post by Stefan Waldmann
A)
String s = "";
for (int i=1; i<=100000; i++) {
s += i;
}
Das ist keine Best Practice.
Post by Stefan Waldmann
B)
StringBuilder sb = new StringBuilder();
for (int i=1; i<=100000; i++) {
sb.append(i);
}
String s = sb.toString();
Das schon.
Ok. Und wie unterscheide ich nun die "Best Practices" von "Programming
Legends"? Letztere sind ja gerade dadurch, dass viele an sie glauben,
auch recht häufig anzutreffen. Also kann man nicht davon ausgehen, dass
alles, was man öfter antrifft, auch Best Practice ist...

Bleibt wohl nur noch das Motto "Versuch macht kluch"... ;-)


Gruß
Stefan
Stefan Matthias Aust
2006-05-20 16:24:50 UTC
Permalink
Post by Stefan Waldmann
Ok. Und wie unterscheide ich nun die "Best Practices" von "Programming
Legends"?
Ganz einfach: Du fragst hier, man antwortet, und wenn kein empörter
Widerspruch kommt, ist das ein Best Practice Pattern :)
Post by Stefan Waldmann
Letztere sind ja gerade dadurch, dass viele an sie glauben,
auch recht häufig anzutreffen.
Wer glauben muss, weil er nicht weiss, ist keine gute Quelle für
Ratschläge. Ob allerdings der, der glaubt zu wissen, jetzt die bessere
Quelle ist...
Post by Stefan Waldmann
Bleibt wohl nur noch das Motto "Versuch macht kluch"... ;-)
Das ist jedenfalls der ehrliche ingenieurmäßige Ansatz... ich wollte
jetzt nicht wissenschaftlich schreiben, wenn das Ausmessen von
Programmen ist nicht wirklich eine Wissenschaft. Will sagen: Eigentlich
ist es einfach.

Andererseits: Benchmarking ist wohl mehr eine schwarze Kunst denn
Wissenschaft und da sind wir dann wieder im Reich der Gold-aus-
Was-weis-ich herstellen wollenden Scharlatane. Alchemisten allgemein zu
verunglimpfen liegt mir fern. Man könnte ihnen höchstens vorwerfen,
wenig innovativ zu sein, wenn sie bis ins 17. Jahrhundert - wie mir
google mitteilte - eigentlich alle ausnahmslos der Vierelement-Lehre von
Aristoteles (also knapp 2000 Jahre lang) anhingen. Doch eigentlich hat
der feste Glaube an einfache Theorien ja auch was positives an sich... oder?
--
Stefan Matthias Aust // Ergo bibamus, ne sitiamus, vas repleamus!
Ingo R. Homann
2006-05-22 08:58:43 UTC
Permalink
Hi,
Post by Stefan Matthias Aust
Andererseits: Benchmarking ist wohl mehr eine schwarze Kunst denn
Wissenschaft und da sind wir dann wieder im Reich der Gold-aus-
Was-weis-ich herstellen wollenden Scharlatane. Alchemisten allgemein zu
verunglimpfen liegt mir fern. Man könnte ihnen höchstens vorwerfen,
wenig innovativ zu sein, wenn sie bis ins 17. Jahrhundert - wie mir
google mitteilte - eigentlich alle ausnahmslos der Vierelement-Lehre von
Aristoteles (also knapp 2000 Jahre lang) anhingen. Doch eigentlich hat
der feste Glaube an einfache Theorien ja auch was positives an sich... oder?
Sofern gegen die 'einfache' Theorie nichts spricht, ist das sogar eine
der Grundlagen von Wissenschaften!

In *der* Hinsicht waren die Alchemisten gar nicht unbedingt
"unwissenschaftlich". Sie waren halt nur sehr stark
"Experimental-wissenschaftlich" ausgerichtet und haben über Jahrhunderte
hinweg immer wieder die gleichen (und wie sich im Nachhinein
herausgestellt hat "falschen") Experimente gemacht...

Ciao,
Ingo
Lothar Kimmeringer
2006-05-30 21:56:13 UTC
Permalink
Post by Stefan Matthias Aust
Post by Stefan Waldmann
Ok. Und wie unterscheide ich nun die "Best Practices" von "Programming
Legends"?
Ganz einfach: Du fragst hier, man antwortet, und wenn kein empörter
Widerspruch kommt, ist das ein Best Practice Pattern :)
Eher ein Least Mecker Pattern. ;-)
Und mit der Definition ist dann auch gleich gezeigt, dass es
kein Best Practice beim Kochen geben kann, denn egal, was man
in de.rec.mampf vorschlaegt, es gibt immer einen, der die
Vorgehensweise fuer schlecht haelt.


Gruesse, Lothar
--
Lothar Kimmeringer E-Mail: ***@kimmeringer.de
PGP-encrypted mails preferred (Key-ID: 0x8BC3CD81)

Always remember: The answer is forty-two, there can only be wrong
questions!
Holger Hoffstaette
2006-05-20 16:21:41 UTC
Permalink
Post by Stefan Waldmann
Ok. Und wie unterscheide ich nun die "Best Practices" von "Programming
Legends"? Letztere sind ja gerade dadurch, dass viele an sie glauben, auch
recht häufig anzutreffen. Also kann man nicht davon ausgehen, dass alles,
was man öfter antrifft, auch Best Practice ist...
Grundlagenwissen. Verständnis für Schichtenmodelle. Neugier. Nachfragen.
Lernen.

-h
Lothar Kimmeringer
2006-05-30 21:53:23 UTC
Permalink
Post by Stefan Waldmann
Ok. Und wie unterscheide ich nun die "Best Practices" von "Programming
Legends"?
Indem man sich mit dem Autor des Codes ein bisschen unterhaelt.
Wir hatten mal eine Gruppe von Indern bei uns, die lieferten
unter anderem folgenden Code ab:

String[] arr = getArrayFromSomewhere();
int index = 0;
try{
while (true){
doSomethingWith(arr[index++]);
}
}
catch(Exception e){}

Auf meine Frage, was das soll (erstens wegen der seltsamen Art
und Weise, ueber das Array zu laufen, als auch das catchen
und Ignorieren saemtlicher Exceptions), bekam ich als Antwort,
dass das schneller sei, als eine for-Schleife, weil man bei
jedem Durchlauf die Ueberpruefung der Indexvariable mit der
Laenge des Arrays vermeidetet, die beim Zugriff auf das Array
ja sowieso gemacht werden wuerde. Wohlgemerkt war das zu Zeiten
von Java 1.1, wo Exceptions noch *richtig* teuer waren (wobei
das heute auch nicht wirklich anders ist).

Den Beweis des preformancetechnischen Gegenteils habe ich mir
dann aber gespart, als die gleiche Person im Laufe des Gespraechs
dann fragte, was ich denn meinen wuerde, wenn ich sagte, dass
eine Klasse ein Interface sei...

Die besten Best Practices sind IMHO die, die man beim ersten
Lesen der Begruendung nachvollziehen kann, z.B. die Vermeidung
folgenden Codes, wenn man mit Maps arbeitet:

if (map.containsKey(key)){
Object val = map.get(key);
// irgendwas wird mit dem Objekt gemacht
}

Da containsKey und get technisch das gleiche machen (was je nach
verwendeter Map-Implementierung durchaus aufwendig sein kann),
containsKey aber an und fuer sich nur als
return get(key) != null;
implentiert ist, sollte man in einem Fall wie oben lieber so
vorgehen:

Object val = map.get(key);
if (val != null){
// irgendwas wird mit dem Objekt gemacht
}

Meine Verwendung von containsKey hat sich seitdem drastisch
reduziert und kommt hoechsten noch in einem Fall wie folgt vor:

if (map.containsKey(key)){
throw new IllegalArgumentException("value already set");
}


Gruesse, Lothar
--
Lothar Kimmeringer E-Mail: ***@kimmeringer.de
PGP-encrypted mails preferred (Key-ID: 0x8BC3CD81)

Always remember: The answer is forty-two, there can only be wrong
questions!
Stefan Ram
2006-05-30 22:07:14 UTC
Permalink
Post by Lothar Kimmeringer
dann aber gespart, als die gleiche Person im Laufe des Gespraechs
dann fragte, was ich denn meinen wuerde, wenn ich sagte, dass
eine Klasse ein Interface sei...
Du meinst, eine Klasse sei ein Interface?
Post by Lothar Kimmeringer
Da containsKey und get technisch das gleiche machen (was je nach
verwendeter Map-Implementierung durchaus aufwendig sein kann),
containsKey aber an und fuer sich nur als
return get(key) != null;
public class Main
{ public static void main( final java.lang.String[] args )
{ final java.util.Map<java.lang.String,java.lang.String> map =
new java.util.HashMap<java.lang.String,java.lang.String>();
map.put( "alpha", null );
if( map.containsKey( "alpha" ))
java.lang.System.out.println( map.get( "alpha" )); }}
Lothar Kimmeringer
2006-05-30 22:29:25 UTC
Permalink
Post by Stefan Ram
Post by Lothar Kimmeringer
dann aber gespart, als die gleiche Person im Laufe des Gespraechs
dann fragte, was ich denn meinen wuerde, wenn ich sagte, dass
eine Klasse ein Interface sei...
Du meinst, eine Klasse sei ein Interface?
Der Dialog verlief in etwa so:

Me: This class-file is an interface.
Him: What do you mean with interface?

Klasse hat in Java ja durchaus mehrere Bedeutungen. Einmal
die, auf die Du anspielst und einmal die Datei, in der
der Bytecode steckt.

Ein anderes Gespraech verlief dann auch noch in etwa so:

Me: The class has to implement the interface Externalizable,
not Serializable.
Him: What is an interface?

Besser verstanden jetzt? Spaetestens nach dem zweiten Dialog
war klar, dass ich mich nicht unklar ausgedrueckt, sonder dem
Betreffenden das Konzept eines Interfaces wirklich nicht klar war.
Post by Stefan Ram
public class Main
{ public static void main( final java.lang.String[] args )
{ final java.util.Map<java.lang.String,java.lang.String> map =
new java.util.HashMap<java.lang.String,java.lang.String>();
map.put( "alpha", null );
if( map.containsKey( "alpha" ))
java.lang.System.out.println( map.get( "alpha" )); }}
Schoenes Beispiel fuer Sourcecodeoptimierung, die ich viel
schlimmer finde als diese for-Schleifen-Optimierung, die mir
bisher ueber den Weg gelaufen ist.

Aber ausser, dass es fuer jede Regel eine Ausnahme gibt, hast
Du doch eigentlich nichts gesagt, oder? Wenn null ein gueltiger
Wert in einer Map ist, klappt der Best Practice natuerlich nicht,
aber dann liesse sich natuerlich streiten, ob es nicht ein Best
Practice waere, fuer null ein dediziertes Objekt zu verwenden.
Die Antwort darauf laesst sich aber nie allgemein sagen, sondern
haengt immer vom jeweilgen Szenario ab (z.B. ob die Map nach
aussen hin sichtbar ist oder nicht).


Gruesse, Lothar
--
Lothar Kimmeringer E-Mail: ***@kimmeringer.de
PGP-encrypted mails preferred (Key-ID: 0x8BC3CD81)

Always remember: The answer is forty-two, there can only be wrong
questions!
Ralf Ullrich
2006-05-30 22:09:17 UTC
Permalink
Post by Lothar Kimmeringer
Die besten Best Practices sind IMHO die, die man beim ersten
Lesen der Begruendung nachvollziehen kann, z.B. die Vermeidung
if (map.containsKey(key)){
Object val = map.get(key);
// irgendwas wird mit dem Objekt gemacht
}
[...] sollte man in einem Fall wie oben lieber so
Object val = map.get(key);
if (val != null){
// irgendwas wird mit dem Objekt gemacht
}
Auch wenn das (fast) stimmt und ich es genauso mache, möchte ich eine
Kleinigkeit ergänzen: Die beiden Codes sind nur dann äquivalent, wenn in
der Map keine "null"-Werte gespeichert sind. (Was praktisch immer der Fall
ist, aber man sollte es in Erinnerung haben, falls man ausnahmsweise doch
mal über den Fall stolpert, dass man eine Map benutzt, die "null"-Werte
enthält.)

cu


PS: Ich sehe gerade Stefan Ram hat auch schon darauf hingewiesen, wenn
auch etwas kryptisch.
Jochen Theodorou
2006-05-30 22:27:07 UTC
Permalink
Lothar Kimmeringer schrieb:
[...]
Post by Lothar Kimmeringer
Die besten Best Practices sind IMHO die, die man beim ersten
Lesen der Begruendung nachvollziehen kann, z.B. die Vermeidung
if (map.containsKey(key)){
Object val = map.get(key);
// irgendwas wird mit dem Objekt gemacht
}
Da containsKey und get technisch das gleiche machen (was je nach
verwendeter Map-Implementierung durchaus aufwendig sein kann),
containsKey aber an und fuer sich nur als
return get(key) != null;
implentiert ist, sollte man in einem Fall wie oben lieber so
Object val = map.get(key);
if (val != null){
// irgendwas wird mit dem Objekt gemacht
}
da unterliegst du aber einem gewissen Irrtum. containsKey ist nicht
get(key)!=null. Es kann durchaus sein, dass man zu einem Key ein null
speichern will/muss, dann geht das mit != null nicht mehr. Und dann
macht es ventuell auch einen Unterschied ob es einen Einträg für diesen
Schlüssel gibt oder nicht. Aber in 90% der Fälle hast du recht, da
reicht get aus.

Gruss theo
christian fein
2006-05-31 18:08:14 UTC
Permalink
Post by Jochen Theodorou
da unterliegst du aber einem gewissen Irrtum. containsKey ist nicht
get(key)!=null. Es kann durchaus sein, dass man zu einem Key ein null
speichern will/muss, dann geht das mit != null nicht mehr. Und dann
macht es ventuell auch einen Unterschied ob es einen Einträg für diesen
Schlüssel gibt oder nicht. Aber in 90% der Fälle hast du recht, da
reicht get aus.
Wobei ich bei sowas die Gefahr der Überperformierung von Code sehe.
Die Map ist für mich keine Collection in der ich unmengen von Daten
speichern will.
Macht es denn dann noch Sinn ein, wenn auch selten, gefährliches
Konstrukt zu nutzen um unmessbare minimale Performance zu erkaufen?

Meiner Erfahrung nach waren unperformante Programmteile immer nur
aufgrund
von falscher Konzepten unperformant.
Sprich synchronisierte Collectionen zu nutzen wo von vorneherein
abzusehen ist das in den entsprechenden Codeteilen Synchronisation
keine Rolle spielt.
Bernd Eckenfels
2006-05-31 20:48:40 UTC
Permalink
Post by christian fein
Wobei ich bei sowas die Gefahr der Überperformierung von Code sehe.
Die Map ist für mich keine Collection in der ich unmengen von Daten
speichern will.
Macht es denn dann noch Sinn ein, wenn auch selten, gefährliches
Konstrukt zu nutzen um unmessbare minimale Performance zu erkaufen?
Naja, gefährlich halte ich es nur null werte zu speichern :)

Ich frage mich ürigens warum es kein "Map.Entry getEntry(Object key)" gibt.
Bei einem Iterator benutzt man das ja auch bevorzugt um nicht nach dem
Iterieren ueber die Keys nochmal ein Lookup zu machen...

Gruss
Bernd
Thomas Kellerer
2006-05-31 21:06:18 UTC
Permalink
Post by Bernd Eckenfels
Ich frage mich ürigens warum es kein "Map.Entry getEntry(Object key)" gibt.
Bei einem Iterator benutzt man das ja auch bevorzugt um nicht nach dem
Iterieren ueber die Keys nochmal ein Lookup zu machen...
Wozu? Wenn Du den key bereits hast, dann hast Du doch nach get(Object key) genau
die gleich Information wie Du in Map.Entry hättest (key, value).

Thomas
Ralf Ullrich
2006-05-31 21:32:27 UTC
Permalink
Post by Thomas Kellerer
Post by Bernd Eckenfels
Ich frage mich ürigens warum es kein "Map.Entry getEntry(Object key)" gibt.
Wozu? Wenn Du den key bereits hast, dann hast Du doch nach get(Object key)
genau die gleich Information wie Du in Map.Entry hättest (key, value).
Nein. Für value==null, liefert getEntry(key) mehr Informationen zurück,
als get(key).

cu
Bernd Eckenfels
2006-06-01 08:22:56 UTC
Permalink
Post by Thomas Kellerer
Wozu? Wenn Du den key bereits hast, dann hast Du doch nach get(Object key) genau
die gleich Information wie Du in Map.Entry hättest (key, value).
Ausser wenn value null ist.

Gruss
Bernd
Marcus Woletz
2006-05-20 19:05:53 UTC
Permalink
Hallo Ralf,

Ralf Ullrich schrieb:

[...]
Post by Stefan Waldmann
Was ist mit "Kleinvieh macht auch Mist"? Wenn ich also an vielen
Stellen die weniger performante Version wähle, summiert sich das nicht
irgendwann so sehr, dass man die Auswirkungen letztendlich zu spüren
bekommt?
Das ist Schwarz-Weiß-Denken. Denn man müsste zuerst einmal für
jede Anwendung definieren, was es bedeutet, die Auswirkungen
"zu spüren zu bekommen".

Ich denke nicht, dass es dieses "weiße Rauschen" in Java gibt, wie an
anderer Stelle bereits geschrieben wurde. Aber ich habe darüber ehrlich
gesagt auch noch nichts gelesen.

Je nach Anwendung lässt es sich auch gar nicht vermeiden, dass
der Anwender Wartezeiten in Kauf nehmen muss, einfach, weil die Aufgabe
entsprechende Rechenzeit benötigt. Wie das der Anwender
dann jedoch zu spüren bekommt, ob z.B. durch eine eingefrorene GUI oder
einen eleganten Fortschrittsbalken mit Abbruchmöglichkeit, liegt in der
Verantwortung des Programmierers.

Jedwede Frage nach der Optimierung erübrigt sich, da sie vollständig
abhängig von der jeweiligen Anwendung ist, jedenfalls makroskopisch.
Und es macht ebenfalls keinen Sinn, in einem O(n^2)-Algorithmus einen
Vergleich um z.B. 10% zu optimieren, nur weil der Profiler eben diesen
Vergleich als Ressourcenfresser meldet, wenn es für dieselbe Aufgabe
einen O(log n)-Algorithmus gibt. Und das sagt einem auch der beste
Profiler der Welt nicht.

Deshalb lässt sich Software auch nicht nach Rezpten entwickeln.
Entwurfsmuster sind praktisch, endbinden den Anwender derselben jedoch
nicht davon, sie sinnvoll einzusetzen.

Deshalb wird auch in 100 Jahren noch keine Maschine nennenswert
komplexe Software entwickeln können. Und selbst wenn es gigantisch
umfangreiche Frameworks geben sollte, wird man Software eben nicht
mehr programmieren, sondern parametrieren, was aber nicht minder komplex
sein kann.

[...]


ciao

Marcus
Ralf Ullrich
2006-05-20 19:53:29 UTC
Permalink
Post by Marcus Woletz
Hallo Ralf,
[...]
Post by Stefan Waldmann
Was ist mit "Kleinvieh macht auch Mist"? Wenn ich also an vielen
Stellen die weniger performante Version wähle, summiert sich das nicht
irgendwann so sehr, dass man die Auswirkungen letztendlich zu spüren
bekommt?
Bitte zitiere richtig!

Der zitierte Text stammt nicht von mir! Richte deinen Post also bitte an
den richtigen Autor!

cu
Wanja Gayk
2006-05-22 13:16:59 UTC
Permalink
Post by Marcus Woletz
Jedwede Frage nach der Optimierung erübrigt sich, da sie vollständig
abhängig von der jeweiligen Anwendung ist, jedenfalls makroskopisch.
Und es macht ebenfalls keinen Sinn, in einem O(n^2)-Algorithmus einen
Vergleich um z.B. 10% zu optimieren, nur weil der Profiler eben diesen
Vergleich als Ressourcenfresser meldet, wenn es für dieselbe Aufgabe
einen O(log n)-Algorithmus gibt. Und das sagt einem auch der beste
Profiler der Welt nicht.
Dann interpretiert man seinen Profiler möglicherweise falsch, weil man
sehr auf das Detail schaut.
Ein Profiler gibt schon an, welche Methode besonders viel Zeit verbrät
und wie oft sie aufgerufen wird. Und man kann durchaus sehen, welche
Methode diese Methode aufgerufen hat, so kann ganz gut von "fein" nach
"grob" durchschauen an irgendeinem Punkt sollte der makroskopische
Zusammenhang auch auffallen.
z.B. könnte dabei auch gut auffallen, dass eine Methode zwar schnell
ist, aber sehr oft aufgerufen wird, was einen schnell auf den
Gedankenbringen sollte, ob es nicht eine Möglichkeit gibt, nicht die
Dauer der Methode, sondern die Anzahl ihrer Aufrufe zu reduzieren, was
einen dann wiederum ganz schnell auf die Sache mit der Komplexität (also
O(n^2) vs. o(n log n)) stößt.

Gruß,
-Wanja-
--
"Gewisse Schriftsteller sagen von ihren Werken immer: 'Mein Buch, mein
Kommentar, meine Geschichte'. [..] Es wäre besser, wenn sie sagten:
'unser Buch, unser Kommentar, unsere Geschichte'; wenn man bedenkt, dass
das Gute darin mehr von anderen ist als von ihnen." [Blaise Pascal]
Sven Drieling
2006-05-19 16:21:12 UTC
Permalink
Stefan Waldmann wrote:

Hallo,
Post by Stefan Waldmann
Post by Michael Paap
Schreibe saubere objektorientierte Anwendungen. Wenn sie schnell genug
für den Anwednungszweck sind, sei glücklich. Wenn nicht, benutze einen
Profiler, um herauszufinden, wo das Problem liegt.
Soweit stimme ich dir zu. Aber heißt dass nun, dass ich mir fortan
überhaupt keine Gedanken mehr zum Thema Performanz machen muss?
*seufz* wieso denn immer von einem ins andere Extrem?

Nein, der "Optimieren: 1. Tue es nicht! 2. Tue es nicht! 3. Tue es nicht!
4. Benutze erst mal einen Profiler"-Ansatz bedeutet nicht, dass
man gar nicht auf Optimierung, Performance und bessere Algorithmen
und Datenstrukturen achten sollte. Nur das hat auch viel
mit Erfahrung zu tun und wenn man diese noch nicht hat, was ständig
der Fall ist, weil immmer wieder was neues hinzukommt, macht es
mehr Sinn erstmal anzufangen und die einfachste Lösung umzusetzen, die
das gewünschte Ergebnis erzielt. Diese Lösung kann man dann durch
den Profiler schicken, gegebenfalls optimieren und die gesammelte
Erfahrung dann in Zukunft nutzen.

Heutzutage sind die Rechner schnell genug, so dass erst mal
die erste, einfache aber dafür fehlerfreie und fertige Lösung reicht.
Das hilft in Kombination mit einem gut les- und wartbaren Quelltext
eher weiter als ein Optimieren jedes einzelnen Codeabschnitts.

Das Hauptproblem besteht eher darin gleich eine Struktur zu finden,
die ein schnelles entwickeln ermöglicht und sich zugleich in Zukunft
leicht erweitern und optimieren lässt, ohne dass alles komplett
neu geschrieben werden muss.


tschuess
[|8:)
Holger Hoffstaette
2006-05-19 16:58:08 UTC
Permalink
wieder was neues hinzukommt, macht es mehr Sinn erstmal anzufangen und
die einfachste Lösung umzusetzen, die das gewünschte Ergebnis erzielt.
Das ist ohne Zweifel ein richtiger Ansatz: Korrektheit ist wichtiger als
Performance. Blöderweise gibt es genug Fälle, in denen Performance
essentieller Teil der Korrektheit (~ Anforderungen) ist, und dann wird es
eben sehr schnell sehr schwierig.
Diese Lösung kann man dann durch den Profiler schicken, gegebenfalls
optimieren und die gesammelte Erfahrung dann in Zukunft nutzen.
Java leidet stärker als andere Sprachen/Umgebungen am "white noise
syndrome", d.h. es lassen sich bei hinreichend komplexer Software oft
keine "hot spots" finden - alles schneckt irgendwie vor sich hin, aber man
weiß nicht, wo die Zeit warum verbraten wird. Und _genau_ daran hakt es
oft, denn Kleinvieh macht nun mal auch Mist. Das JDK selbst ist hier an
vielen Stellen so konzeptionell kaputt, daß man sich nicht wundern muß,
warum der Schichtensalat obendrauf gar nicht schnell gemacht werden kann -
es sei denn man erfindet ganze Codepfade (Abkürzungen) neu, was ja dann
auch gerne gemacht wird - bizarrerweise sogar innerhalb des JDK.
Das Hauptproblem besteht eher darin gleich eine Struktur zu finden, die
ein schnelles entwickeln ermöglicht und sich zugleich in Zukunft leicht
erweitern und optimieren lässt, ohne dass alles komplett neu geschrieben
werden muss.
Wahre Worte.

Holger
Stefan Waldmann
2006-05-20 15:21:29 UTC
Permalink
Post by Sven Drieling
Hallo,
Post by Stefan Waldmann
Post by Michael Paap
Schreibe saubere objektorientierte Anwendungen. Wenn sie schnell genug
für den Anwednungszweck sind, sei glücklich. Wenn nicht, benutze einen
Profiler, um herauszufinden, wo das Problem liegt.
Soweit stimme ich dir zu. Aber heißt dass nun, dass ich mir fortan
überhaupt keine Gedanken mehr zum Thema Performanz machen muss?
*seufz* wieso denn immer von einem ins andere Extrem?
Naja, weil der eine oder andere die obige Aussage durchaus so verstehen
könnte.
Post by Sven Drieling
Nein, der "Optimieren: 1. Tue es nicht! 2. Tue es nicht! 3. Tue es nicht!
4. Benutze erst mal einen Profiler"-Ansatz bedeutet nicht, dass
man gar nicht auf Optimierung, Performance und bessere Algorithmen
und Datenstrukturen achten sollte. Nur das hat auch viel
mit Erfahrung zu tun und wenn man diese noch nicht hat, was ständig
der Fall ist, weil immmer wieder was neues hinzukommt, macht es
mehr Sinn erstmal anzufangen und die einfachste Lösung umzusetzen, die
das gewünschte Ergebnis erzielt. Diese Lösung kann man dann durch
den Profiler schicken, gegebenfalls optimieren und die gesammelte
Erfahrung dann in Zukunft nutzen.
Guter Punkt. Wenn ich mit eigenen Augen gesehen habe, dass Lösung A
performanter ist als B, ist es auch sinnvoll, künftig Lösung A
einzusetzen (wobei A nicht unbedingt für alle Anwendungsfälle die beste
Wahl sein muss).

Wenn ich allerdings jeder "Programming Legend" glaube, die ich jemals
irgendwo gelesen habe - z.B. das mit den Rückwärtsschleifen - kann das
durchaus kontraproduktiv sein, da ich mich mehr mit Pseudo-Optimierung
beschäftige als mit der eigentlichen Lösung meines Problems.
Post by Sven Drieling
Das Hauptproblem besteht eher darin gleich eine Struktur zu finden,
die ein schnelles entwickeln ermöglicht und sich zugleich in Zukunft
leicht erweitern und optimieren lässt, ohne dass alles komplett
neu geschrieben werden muss.
Da kann ich nur Holger zitieren: Wahre Worte ;-)


Gruß
Stefan
Holger Hoffstaette
2006-05-19 16:19:34 UTC
Permalink
StringBuilder sb = new StringBuilder(); for (int i=1; i<=100000; i++) {
sb.append(i);
}
String s = sb.toString();
Großartige Steilvorlage, die die ganze Absurdität dieser Diskussionen
prima offenbart: eine "premature optimization" durch new StringBuilder(x)
mit x ~~ (Anzahl der Werte * Länge eines Wert) wäre in diesem Fall eine vom
Preis/Leistungsverhältnis unschlagbare "Optimierung", die wirklich was
bringt. Das ändert natürlich nichts daran, daß die Dein Antibeispiel A)
leider dennoch "Standard" in vielen Programmen ist. Auch am sb.append()
könnte man intern viel machen aber das lasse ich jetzt besser weg, sonst
rege ich mich nur wieder über Sun auf.
Was ist mit "Kleinvieh macht auch Mist"? Wenn ich also an vielen Stellen
Mikrooptimierungen sind entegegen der gebetsmühlenartigen Rezitierung des
Knuth-Zitats selbstverständlich hochrelevant, wenn es um die Wurst geht -
*für die Implementierung des richtigen Algorithmus*. Das steht keineswegs
im Widerspruch zu Knuths Zitat oder der üblichen Praxis, die "niedrig
hängenden Früchte" natürlich zuerst zu pflücken.

Andererseits ist immer wieder festzustellen, daß die größten Klopper gar
nicht so sehr Implementierungs- sondern fundamentale Architekturmängel
sind - wenn man schon nicht weiß wie ein Betriebssystem funktioniert, wie
soll man dann noch wissen wie man Latenz, Bandbreite, Durchsatz und CPU in
einer verteilten Umgebung unter einen Hut bringt?
die weniger performante Version wähle, summiert sich das nicht irgendwann
so sehr, dass man die Auswirkungen letztendlich zu spüren bekommt?
Selbstverständlich tut es das, und nicht zu knapp - in Java nur anders als
in anderen Sprachen, was das Übertragen von folkloreartig kolportierten,
nicht verstandenen "Optimierungslegenden" wie z.B. das erwähnte
rückwärtszählen so sinnlos macht. Ingos Behauptung ist für viele
Entwickler leider nichts anderes als ein Freibrief, scheiße zu
programmieren - schließlich kann man das ja noch später beheben.
Blöd (oder lustig, je nach Standpunkt :) wird es dann immer, wenn der
Superarchitekt mehr Server, mehr GigaHurtz, mehr RAM und mehr sonstwas
kauft, aber die App genau garnicht schneller wird.

Holger
Timo Stamm
2006-05-19 14:12:53 UTC
Permalink
ich habe eine Frage bzgl. der Effizienz von Java. [...]
Beispiel: Hat man eine for-Schleife "for (int i = 0; i < 10000; i++)
{}" dann habe ich gelesen, dass man in so einem Fall nicht von 0 bis
10000 hoch zählen soll, sondern von 10000 runter bis 0. Warum? Weil
die Abbruchbedingung der Schleife ein Vergleich ist und der Vergleich
mit 0 schneller behandelt wird als der Vergleich mit (hier) 10000.
Also: for (int i = 9999; i >= 0; i--)
Sorry, leider nur auf Englisch:


A "micro-optimization" is a performance optimization at a low level. For
example, the following construct:

for( int i = upperbound; 0 != i--; ) {
// ...
}

is supposed to be more efficient than

for( int i = 0; i < upperbound; i++ ) {
// ...
}

This is actually true, the former construct can be more efficient in
statically compiled languages. But in a language like Java, which is
compiled into byte code and interpreted by a virtual machine that can
theoretically run on any platform, such optimizations don't make much
sense for several reasons:

The latter construct is standard - every programmer who knows languages
influenced by C will understand it at the first glance. Using your own
constructs will make the code harder to read for anybody else, which may
lead to more time-consuming maintenance and more bugs.

You can not be sure that this micro-optimization gains you any
performance, because the Java VM has a just-in-time compiler that works
under the assumption that you wrote plain java code. If this JIT
compiler recognizes standard for loops and optimizes them, you might
even loose performance.

The same goes for assumptions about a lot of other constructs, about
memory management, etc.

Those optimizations have one thing in common: They are not made because
a programm runs too slow. They are premature. Donald Knuth said "We
should forget about small efficiencies, say about 97% of the time:
premature optimization is the root of all evil."

So you should never waste any time on optimization unless you have made
tests, clearly identified the bottleneck, and are able to change your
design accordingly. I am sure it will almost never be the for loop you
have to optimize.
Dirk Dittert
2006-05-29 17:57:28 UTC
Permalink
Post by Timo Stamm
A "micro-optimization" is a performance optimization at a low level. For
for( int i = upperbound; 0 != i--; ) {
// ...
}
is supposed to be more efficient than
for( int i = 0; i < upperbound; i++ ) {
// ...
}
Das macht IMHO überhaupt keinen Sinn. Es mag sein, daß man ersteres 1:1
in schnelleren Code übersetzen kann, wenn aber 99% der Programmierer die
zweite Version verwenden, dann sollte der Compilerhersteller dafür
sorgen, daß für die zweite Version (wenn möglich) ebenso effizienter
Code produziert wird.

Viele Grüße,

Dirk Dittert
Timo Stamm
2006-05-29 20:30:10 UTC
Permalink
Post by Dirk Dittert
Post by Timo Stamm
A "micro-optimization" is a performance optimization at a low level. For
for( int i = upperbound; 0 != i--; ) {
// ...
}
is supposed to be more efficient than
for( int i = 0; i < upperbound; i++ ) {
// ...
}
Das macht IMHO überhaupt keinen Sinn.
Doch, denn den Vergleich mit 0 können gängige Prozessoren schneller
machen. Roedy Green hat dazu etwas geschrieben:
http://groups.google.com/group/comp.lang.java.programmer/tree/browse_frm/thread/c00d2ddbe75b5f3f/7f5bad344db8d2bb?rnum=11&_done=%2Fgroup%2Fcomp.lang.java.programmer%2Fbrowse_frm%2Fthread%2Fc00d2ddbe75b5f3f%2Fea972d11ce29608b%3F#doc_d159e46292220778
Post by Dirk Dittert
Es mag sein, daß man ersteres 1:1
in schnelleren Code übersetzen kann, wenn aber 99% der Programmierer die
zweite Version verwenden, dann sollte der Compilerhersteller dafür
sorgen, daß für die zweite Version (wenn möglich) ebenso effizienter
Code produziert wird.
Genauso effizient geht nicht, denn du kannst die Reihenfolge einer
Schleife nicht beliebig umkehren. Es liegt also am Programmierer das
Design entsprechend auszulegen dass die Schleife zumindest umkehrbar ist.

Warum es trotzdem keinen Sinn macht in Java so zu optimieren schrieb ich ja.


Timo
Ralf Ullrich
2006-05-29 20:43:51 UTC
Permalink
Post by Dirk Dittert
Das macht IMHO überhaupt keinen Sinn.
Doch, [das macht Sinn.]
Warum es trotzdem keinen Sinn macht [...] schrieb ich ja.
Kannst du dich mal für eins entscheiden?
Timo Stamm
2006-05-29 21:10:27 UTC
Permalink
Post by Ralf Ullrich
Post by Dirk Dittert
Das macht IMHO überhaupt keinen Sinn.
Doch, [das macht Sinn.]
Warum es trotzdem keinen Sinn macht [...] schrieb ich ja.
Kannst du dich mal für eins entscheiden?
Nein, es gibt nämlich zwei Aspekte. Erstens kann die Optimierung in
einer Sprache wie C Sinn machen, zweitens macht sie in Java keinen Sinn.

Steht auch alles klar und deutlich in meinem Posting auf das Dirk
geantwortet hat, du musst es nur lesen.


Timo
Ralf Ullrich
2006-05-29 21:33:14 UTC
Permalink
Post by Ralf Ullrich
Post by Dirk Dittert
Das macht IMHO überhaupt keinen Sinn.
Doch, [das macht Sinn.]
Warum es trotzdem keinen Sinn macht [...] schrieb ich ja.
Kannst du dich mal für eins entscheiden?
Nein, es gibt nämlich zwei Aspekte. Erstens kann die Optimierung in einer
Sprache wie C Sinn machen, zweitens macht sie in Java keinen Sinn.
Steht auch alles klar und deutlich in meinem Posting auf das Dirk
geantwortet hat, du musst es nur lesen.
OK, wenn du das so gemeint hast: "Doch, [bei maschinennahen Sprachen wie C
macht das Sinn] ... Warum es [bei Java] keinen Sinn macht [...] schrieb
ich ja."

Dann verstehe ich was du meinst. Und dann hast du natürlich auch völlig
recht.

cu
Stefan Ram
2006-05-29 21:27:35 UTC
Permalink
Post by Timo Stamm
Post by Dirk Dittert
Post by Timo Stamm
for( int i = upperbound; 0 != i--; ) {
for( int i = 0; i < upperbound; i++ ) {
Das macht IMHO überhaupt keinen Sinn.
Doch, denn den Vergleich mit 0 können gängige Prozessoren schneller
Aber wenn man nun einmal aufwärts zählen /will/, dann hilft es
ja nichts, wenn etwas anderes schneller wäre.
Auf dem Amiga war "++i;" bei Lattice C (SAS C) wohl
tatsächlich schneller als "i++;", da im zweiten Fall immer
noch der alte Wert gespeichert wurde. Heute sind die
Optimierer vermutlich etwas weiter.
Post by Timo Stamm
Genauso effizient geht nicht, denn du kannst die Reihenfolge einer
Zum n-fachen wiederholen, wenn es egal ist, ob aufwärts oder
abwärts, sollte es eine spezielle Anweisung geben:

repeat( upperbound )...

So etwas gibt es wohl in Common Lisp.

Notfalls definiert man für Java ein Makro.

Folgendes gibt bei mir sechs mal »alpha« aus:

public class Main
{ public static void main ( final java.lang.String[] args )
{ REPEAT( 2 )
REPEAT( 3 )
java.lang.System.out.println( "alpha" ); }}

Der Vorverarbeiter erzeugt:

public class Main
{ public static void main ( final java.lang.String[] args )
{ for(int SYM1=( 2 );(SYM1--)!=0;)
for(int SYM2=( 3 );(SYM2--)!=0;)
java.lang.System.out.println( "alpha" ); }}

vermittels folgender Makro-Definitionen für den Vorverarbeiter "gpp":

$mode save

$mode standard HTML

<#define REPEATNAME|0>
<#define NEXTSYM|<#defeval REPEATNAME|<#eval 1+<#REPEATNAME>>>>
<#define REPEAT|<#NEXTSYM>for(int SYM<#REPEATNAME>=(#1);(SYM<#REPEATNAME>--)!=0;)>

<#mode restore>

Mein Java-Makro-Modus erlaubt zwar zu Java passende Aufruf
(»REPEAT( 2 )«) statt für Java fremdartige Aufrufe ("<#REPEAT
2>") ist aber für kompliziertere Makrodefinition etwas
beschränkt. Daher wechsele ich zunächst in den HTML-Modus.
Dann kann ich die Makros bequemer definieren und wieder zurück
in den Java-Modus wechseln.
Dirk Dittert
2006-05-30 18:11:22 UTC
Permalink
Post by Timo Stamm
Genauso effizient geht nicht, denn du kannst die Reihenfolge einer
Schleife nicht beliebig umkehren. Es liegt also am Programmierer das
Design entsprechend auszulegen dass die Schleife zumindest umkehrbar ist.
Mir ist natürlich bewußt, daß man die Zählrichtung nicht beliebig ändern
kann. Mein Argument ist, daß Schleifen in dieser Ausprägung (also
aufwärts zählend) oft dafür verwendet werden, um über etwas zu
iterieren. Und diese Verwendung sollte der Compiler für mich bestmöglich
optimieren. Daß das nicht immer automatisch funktionieren kann, ist mir
klar.

Viele Grüße,

Dirk Dittert
Timo Stamm
2006-05-30 22:26:08 UTC
Permalink
Post by Dirk Dittert
Post by Timo Stamm
Genauso effizient geht nicht, denn du kannst die Reihenfolge einer
Schleife nicht beliebig umkehren. Es liegt also am Programmierer das
Design entsprechend auszulegen dass die Schleife zumindest umkehrbar ist.
Mir ist natürlich bewußt, daß man die Zählrichtung nicht beliebig ändern
kann. Mein Argument ist, daß Schleifen in dieser Ausprägung (also
aufwärts zählend) oft dafür verwendet werden, um über etwas zu
iterieren. Und diese Verwendung sollte der Compiler für mich bestmöglich
optimieren.
Laut "Java Performance Tuning" von Jack Shirazi optimieren aktuelle JVMs
mit JIT die Standard for-Schleife. Damit kann man zwar logischerweise
trotzdem nie so schnell sein wie mit einem garantierten absteigenden
Index schon im Source, aber der Unterschied ist noch mal weniger relevant.


Timo
Paul Ebermann
2006-05-30 23:18:15 UTC
Permalink
Post by Timo Stamm
Post by Dirk Dittert
Post by Timo Stamm
Genauso effizient geht nicht, denn du kannst die Reihenfolge einer
Schleife nicht beliebig umkehren. Es liegt also am Programmierer das
Design entsprechend auszulegen dass die Schleife zumindest umkehrbar ist.
Mir ist natürlich bewußt, daß man die Zählrichtung nicht beliebig ändern
kann. Mein Argument ist, daß Schleifen in dieser Ausprägung (also
aufwärts zählend) oft dafür verwendet werden, um über etwas zu
iterieren. Und diese Verwendung sollte der Compiler für mich bestmöglich
optimieren.
Laut "Java Performance Tuning" von Jack Shirazi optimieren aktuelle JVMs
mit JIT die Standard for-Schleife. Damit kann man zwar logischerweise
trotzdem nie so schnell sein wie mit einem garantierten absteigenden
Index schon im Source, aber der Unterschied ist noch mal weniger relevant.
Und wenn es dabei darum geht, ein Array zu durchlaufen,
werden wohl einige Optimierer dann den Array-Bounds-Check
bei der Vorwärts-Schleife einsparen können, bei der
Rückwärts-Schleife eher nicht.

Und schon ist der Unterschied umgekehrt ...


Paul
--
Wem es darum zu tun ist, dauerhafte Achtung sich zu erwerben; [...] der würze
nicht ohne Unterlass seine Gespräche mit Lästerungen, Spott und Medisance und
gewöhne sich nicht an den auszischenden Ton von Persiflage.
Adolf Freiherr Knigge, Über den Umgang mit Menschen, 1.17
Stefan Ram
2006-05-30 23:56:45 UTC
Permalink
Post by Paul Ebermann
Und wenn es dabei darum geht, ein Array zu durchlaufen,
werden wohl einige Optimierer dann den Array-Bounds-Check
bei der Vorwärts-Schleife einsparen können, bei der
Rückwärts-Schleife eher nicht.
Wenn ich eine Reihung mit einer Kennzahl i durchlaufen will
und mir die Richtung egal ist, dann sollte ich das auch in der
Programmiersprache sagen können.

foreach( int i: indexof a )
{ java.lang.System.out.println( a[ i ]); }

Dann soll der Optimierer die schnellste Richtung
auswählen.

Varianten dieser Anweisung wären dann:

foreach( int i: ascending indexof a )...
foreach( int i: descending indexof a )...
Ralf Ullrich
2006-05-31 00:20:50 UTC
Permalink
Post by Stefan Ram
Post by Paul Ebermann
Und wenn es dabei darum geht, ein Array zu durchlaufen,
werden wohl einige Optimierer dann den Array-Bounds-Check
bei der Vorwärts-Schleife einsparen können, bei der
Rückwärts-Schleife eher nicht.
Wenn ich eine Reihung mit einer Kennzahl i durchlaufen will
und mir die Richtung egal ist, dann sollte ich das auch in der
Programmiersprache sagen können.
foreach( int i: indexof a )
{ java.lang.System.out.println( a[ i ]); }
Dann soll der Optimierer die schnellste Richtung
auswählen.
foreach( int i: ascending indexof a )...
foreach( int i: descending indexof a )...
Schön wärs, aber im Falle von Java wäre der Nutzen bezgl.
Optimierungsmöglichkeiten verschwindend gering:

Die Anweisung müsste vom Java Compiler wie üblich zunächst in Bytecode
übersetzt werden. Dort gibt es (wie in Assembler) keine Schleifen, sondern
Labels/Adressen und Sprünge.

Ohne es jetzt lange darzulegen: Letztlich müsste der gleiche Bytecode
erzeugt werden, wie für die heute schon vorhandene for-schleife. Und im
Fall, dass man weder ascending noch descending angibt, steht der Java
Compiler vor dem gleichen Problem, wie jetzt der Programmierer: Welche
Richtung wird wohl auf der Zielmaschine, die zur Compile-Time unbekannt
ist, letztlich die bessere LIR-Optimierung zulassen? Auf Bytecode-Ebene
sind beide Richtungen gleichwertig. Wie jetzt der Programmierer, müsste
der der Java-Compiler eine der beiden Varianten mehr oder minder "aus dem
Bauch heraus" vorziehen.


Nicht einmal für das einsparen des Boundary-Checks würde sich diese neue
Schleifen-Syntax eignen, obwohl sie in ihrer Ausdrucksweise, gerade das
nahelegen könnte. Denn im Bytecode wären wieder die üblichen Ausdrücke
(int i = 0;i<a.length bzw. int i=a.length-1;i>=0) codiert.

cu
Gerd K.
2006-05-31 06:02:21 UTC
Permalink
Hallo zusammen!

Nur mal so zur Diskussion:

Was nutzt die ganze Diskussion um Laufzeiteffizienz, wenn der
Programmierer dummerweiser einen Algorithmus gewählt hat, der in einer
Komplexitätsklasse liegt, die keine spürbare Effizienzsteigerung er-
laubt? Will damit sagen: Diese ganze Diskussion um Millisekunden
ist nutzlos, sinnlos und m.E. schädlich. Viel wichtiger
ist ein sauberes Software Engineering (Software erstellen ist so viel
mehr
als Programmieren/Einhacken), dann erübrigt sich das alles.
Und dafür ist der Software Engineering Experte zuständig,
nicht der einfache Programmierer. Nicht umsonst trennt diese
in der Regel ein vierjähriges Uni-Studium...

Dem Kunden ist es doch egal, ob er 3 Sekunden oder 3,05 Sekunden
auf sein Ergebnis warten muss, Hauptsache, es ist korrekt ;-)

Viel wichtiger als "effizienter" Programmcode ist doch lesbarer,
wartbarer Code. Und Code, der die letzten Millisekunden herausholt,
wird bestimmt nicht mehr gut wartbar sein ;-)

Grüße,
Gerd
Ralf Ullrich
2006-05-31 10:10:30 UTC
Permalink
Post by Gerd K.
Was nutzt die ganze Diskussion um Laufzeiteffizienz, wenn der
Programmierer dummerweiser einen Algorithmus gewählt hat, der in einer
Komplexitätsklasse liegt, die keine spürbare Effizienzsteigerung er-
laubt? Will damit sagen: Diese ganze Diskussion um Millisekunden
ist nutzlos, sinnlos und m.E. schädlich.
Und dafür ist der Software Engineering Experte zuständig,
nicht der einfache Programmierer. Nicht umsonst trennt diese
in der Regel ein vierjähriges Uni-Studium...
Viel wichtiger als "effizienter" Programmcode ist doch lesbarer,
wartbarer Code. Und Code, der die letzten Millisekunden herausholt,
wird bestimmt nicht mehr gut wartbar sein ;-)
Während du einerseits recht hast, das es jederzeit besser ist, den
verwendeten Algorithmus durch einen schnelleren zu ersetzen, vergisst du
aber dann doch noch etwas: Was tun, denn der verwendete Algorithmus
bereits der schnellste anwendbare ist, und das Programm immer noch zu
langsam ist?

Nimm doch zum Beispiel die letzte Quizaufgabe mit den Fraktalen Strings.
Da gab es zwei Algorithmen zur Auswahl. Bei dem einen (dem rekursiven) war
die Laufzeit exponentiell, aber dafür der Speicherverbrauch linear. Bei
dem anderen (dem mit precaching) war, war dagegen der Speicherverbrauch
exponentiell, während die Laufzeit (nach dem der Cache gefüllt ist)
konstant ist.

Der Precaching Algorithmus, war ab einer gewissen Ersetzungsstufe schlicht
nicht mehr anwendbar, was dann den rekursiven zum einzigen verfügbaren
Algorithmus gemacht hat.

Und damit warst du dann als Programmierer in der Situation, dass dir dein
ach so studierter Software Engineering Experte auch nicht mehr mit einem
besseren Algorithmus helfen konnte. Um jetzt noch geschwindigkeit
herauszuhohlen musst du in dieses Wettrennen um Millisekunden einsteigen.

Ich bestreite gar nicht, dass das Ergebnis einer solchen Optimierung
schlechter lesbar und wartbar ist. Aber manchmal sind die letzten
Millisekunden so wichtig, dass das keine Rolle spielt.


Das Fraktale Strings Beispiel ist natürlich sinnfrei, aber wenn du mal in
der Praxis Code schreiben willst, bei denen diese Art der Optimierung das
tägliche Brot eines "Programmierungs-Experten" ist, dann versuch dich doch
an einem Charset-Encoder/Decoder, an einer MessageDigest Implementierung,
an einem Filter zur Bildbearbeitung, an einem Audio- oder Video-Codec, usw.

cu
Gerd K.
2006-05-31 10:51:43 UTC
Permalink
Post by Ralf Ullrich
Ich bestreite gar nicht, dass das Ergebnis einer solchen Optimierung
schlechter lesbar und wartbar ist. Aber manchmal sind die letzten
Millisekunden so wichtig, dass das keine Rolle spielt.
Und hier behaupte ich, dass das für 99% der Programmierer
nie eine Rolle spielt, weil die sich in Problemdomänen bewegen,
die alles andere als zeitkritisch sind ;-) Und für solche
Programmierer halte ich die angestossene Diskussion einfach nur
für schädlich. Die probieren einige "Tricks" vielleicht mal
aus *gg*
Post by Ralf Ullrich
Das Fraktale Strings Beispiel ist natürlich sinnfrei, aber wenn du mal in
der Praxis Code schreiben willst, bei denen diese Art der Optimierung das
tägliche Brot eines "Programmierungs-Experten" ist, dann versuch dich doch
an einem Charset-Encoder/Decoder, an einer MessageDigest Implementierung,
an einem Filter zur Bildbearbeitung, an einem Audio- oder Video-Codec, usw.
Ok, aber für solche Aufgaben gibt es doch bessere Sprachen als Java *g*
Eine Hochsprache einzusetzen und dann um Millisekunden zu kämpfen deutet
auf Fehler hin, die in früheren Aktivitäten der Softwareentwicklung
gemacht worden sind.

Noch eine Anmerkung zu den von Dir so genannten
"ach so studierten Software Engineering Experten":
Diese Leute sind in der Lage, sich sicher auf unterschiedlichsten
Abstraktionsniveaus zu bewegen (sonst sind es in meinen Augen keine
Software Engineering Experten) und das ist bei der Erstellung
von Software unerlässlich. In der wichtigsten
Aktivität (weil Fehler hier am teuersten sind ;-) ) des Requierement
Engineerings müssen sie die Realwelt modellieren und zwar so,
dass einerseits der Kunde die Anforderungen validieren kann, anderer-
seits die Ergebnisse aber auch eine Basis für den weiteren
Verlauf der Softwareerstellung bilden. Boehm beschreibt diesen
Spagat treffend mit "Are we buildung the right product?" und
"Are we building the product right?". Ein "normaler" Programmierer
wird an dieser Aufgabe scheitern, weil er viel zu imple-
mentierungsnah denkt. Und solche Effizienzdiskussionen wie die
hier angestossene verstärken diese Scheuklappensicht nur.

Viele Grüße,
Gerd
Michael Hüttermann
2006-05-31 11:08:31 UTC
Permalink
Post by Gerd K.
Post by Ralf Ullrich
Ich bestreite gar nicht, dass das Ergebnis einer solchen Optimierung
schlechter lesbar und wartbar ist. Aber manchmal sind die letzten
Millisekunden so wichtig, dass das keine Rolle spielt.
Und hier behaupte ich, dass das für 99% der Programmierer
nie eine Rolle spielt, weil die sich in Problemdomänen bewegen,
die alles andere als zeitkritisch sind ;-) Und für solche
Programmierer halte ich die angestossene Diskussion einfach nur
für schädlich. Die probieren einige "Tricks" vielleicht mal
aus *gg*
glaub ich auch dass sich meistens der optimierungsaufwand nicht lohnt
oder am falschen ende pseudo-optimiert wird
Post by Gerd K.
Noch eine Anmerkung zu den von Dir so genannten
Diese Leute sind in der Lage, sich sicher auf unterschiedlichsten
Abstraktionsniveaus zu bewegen (sonst sind es in meinen Augen keine
Software Engineering Experten) und das ist bei der Erstellung
von Software unerlässlich. In der wichtigsten
Aktivität (weil Fehler hier am teuersten sind ;-) ) des Requierement
Engineerings müssen sie die Realwelt modellieren und zwar so,
dass einerseits der Kunde die Anforderungen validieren kann, anderer-
seits die Ergebnisse aber auch eine Basis für den weiteren
Verlauf der Softwareerstellung bilden. Boehm beschreibt diesen
Spagat treffend mit "Are we buildung the right product?" und
"Are we building the product right?". Ein "normaler" Programmierer
wird an dieser Aufgabe scheitern, weil er viel zu imple-
mentierungsnah denkt. Und solche Effizienzdiskussionen wie die
hier angestossene verstärken diese Scheuklappensicht nur.
deswegen denke ich auch der Kunde sollte die Anforderungen artikulieren
und aufschreiben. Das grösste Risiko in einem Projekt ist, dass etwas
entwickelt wird was der Kunde nicht möchte. Von den Rollen Programmierer
und sowas halte ich nicht soviel. Das hängt aber wohl damit zusammen,
dass ich die Agile Entwicklung schwergewichtigen vorziehe.
--
best regards

Michael Hüttermann

http://jugcologne.org
http://huettermann.net
AIM: javageekkoeln
Gerd K.
2006-05-31 13:28:13 UTC
Permalink
Post by Michael Hüttermann
deswegen denke ich auch der Kunde sollte die Anforderungen artikulieren
und aufschreiben.
Der Kunde sollte so weit wie möglich benutzt werden, um die
Anforderungen zu finden. ;-)
Er alleine kennt aber nicht die (notwendige) formale Notation
der Anforderungen, sondern er wird es "umgangssprachlich" machen.
Und in der Regel weiß er nicht, was er will.
Hier stellt das Requierements Engineering Mittel und
Wege zur Verfügung, dass aus ihm herauszubekommen.
Post by Michael Hüttermann
Das grösste Risiko in einem Projekt ist, dass etwas
entwickelt wird was der Kunde nicht möchte.
Genau!
Post by Michael Hüttermann
Von den Rollen Programmierer
und sowas halte ich nicht soviel. Das hängt aber wohl damit zusammen,
dass ich die Agile Entwicklung schwergewichtigen vorziehe.
Es gibt viele Papiere zum Thema Qualität von Vorgehensmodellen
der Softwareentwicklung. Mein persönliches Fazit: Sind die Entwickler
sehr gut, ist die Methodik egal, das Ergebnis wird gut sein. ;-)
Leider gibt es zu wenig gute Entwickler. In meinen Augen ist ein
Vorgehensmodell daher dann besser als ein anderes, wenn es mehr
mittelmäßige oder schlechte Programmierer verkraftet ;-))
Deswegen bin ich ein Anhänger der modellbasierten Softwareentwicklung
mit geringen Anteil der automatischen Generierung.

Grüße
Michael Hüttermann
2006-05-31 14:07:02 UTC
Permalink
Post by Gerd K.
Post by Michael Hüttermann
deswegen denke ich auch der Kunde sollte die Anforderungen artikulieren
und aufschreiben.
Der Kunde sollte so weit wie möglich benutzt werden, um die
Anforderungen zu finden. ;-)
Er alleine kennt aber nicht die (notwendige) formale Notation
der Anforderungen, sondern er wird es "umgangssprachlich" machen.
Und in der Regel weiß er nicht, was er will.
Hier stellt das Requierements Engineering Mittel und
Wege zur Verfügung, dass aus ihm herauszubekommen.
Es muss auch keine "formale Notation" gefunden werden. Es ist besser
wenn alle Parteien mit dem selben Vokabular arbeiten.
Post by Gerd K.
Es gibt viele Papiere zum Thema Qualität von Vorgehensmodellen
der Softwareentwicklung. Mein persönliches Fazit: Sind die Entwickler
sehr gut, ist die Methodik egal, das Ergebnis wird gut sein. ;-)
Leider gibt es zu wenig gute Entwickler. In meinen Augen ist ein
Vorgehensmodell daher dann besser als ein anderes, wenn es mehr
mittelmäßige oder schlechte Programmierer verkraftet ;-))
Deswegen bin ich ein Anhänger der modellbasierten Softwareentwicklung
mit geringen Anteil der automatischen Generierung.
es ist besser sehr gute Entwickler mit miserablen Tools und Prozessen zu
haben als sehr miese Entwickler mit exzellenten Tools und fantastischen
Prozessen, das ist absolut richtig! Zu Deinem Post möchte ich noch
ergänzen, dass es darum geht als "Team" erfolgreich zu sein. Es gibt
nicht *den* schlechten Entwickler...jeder hat Stärken und Schwächen.
--
best regards

Michael Hüttermann

http://jugcologne.org // Java User Group Cologne site
http://huettermann.net // my site
AIM: javageekkoeln // instant contact

"More users find more bugs.", Frederick P. Brooks, Jr. (1975)
Wanja Gayk
2006-06-02 06:56:18 UTC
Permalink
Post by Gerd K.
Was nutzt die ganze Diskussion um Laufzeiteffizienz, wenn der
Programmierer dummerweiser einen Algorithmus gewählt hat, der in einer
Komplexitätsklasse liegt, die keine spürbare Effizienzsteigerung er-
laubt? Will damit sagen: Diese ganze Diskussion um Millisekunden
ist nutzlos, sinnlos und m.E. schädlich.
1000 Millisekunden sind eine Sekunde.

Sprich: Ob die Millisekunde zählt kommt ganz darauf an, wie heiß der
Code ist.

Gruß,
-Wanja-
--
"Gewisse Schriftsteller sagen von ihren Werken immer: 'Mein Buch, mein
Kommentar, meine Geschichte'. [..] Es wäre besser, wenn sie sagten:
'unser Buch, unser Kommentar, unsere Geschichte'; wenn man bedenkt, dass
das Gute darin mehr von anderen ist als von ihnen." [Blaise Pascal]
Paul Ebermann
2006-05-31 10:59:20 UTC
Permalink
Post by Ralf Ullrich
Post by Stefan Ram
Post by Paul Ebermann
Und wenn es dabei darum geht, ein Array zu durchlaufen,
werden wohl einige Optimierer dann den Array-Bounds-Check
bei der Vorwärts-Schleife einsparen können, bei der
Rückwärts-Schleife eher nicht.
Wenn ich eine Reihung mit einer Kennzahl i durchlaufen will
und mir die Richtung egal ist, dann sollte ich das auch in der
Programmiersprache sagen können.
foreach( int i: indexof a )
{ java.lang.System.out.println( a[ i ]); }
Dann soll der Optimierer die schnellste Richtung
auswählen.
foreach( int i: ascending indexof a )...
foreach( int i: descending indexof a )...
Schön wärs, aber im Falle von Java wäre der Nutzen bezgl.
Die Anweisung müsste vom Java Compiler wie üblich zunächst in Bytecode
übersetzt werden. Dort gibt es (wie in Assembler) keine Schleifen, sondern
Labels/Adressen und Sprünge.
Dann muss man eben den Bytecode mit anpassen,
sei doch nicht so unkreativ ...

In Fortress (die neue Sprache von Sun, an der zur Zeit
gearbeitet wird - http://research.sun.com/projects/plrg/)
ist für Schleifen standardmäßig die Reihenfolge der
Ausführung nicht vorgegeben, und kann parallel auch erfolgen.

Eine Umsetzung in Java-Bytecode ist da natürlich nicht
so einfach machbar.


Paul
--
Die Homepage von de.comp.lang.java: http://www.dclj.de
Pauls Package-Sammlung: http://purl.org/NET/ePaul/#pps
Stefan Matthias Aust
2006-05-20 07:33:04 UTC
Permalink
Post by Ulrich Frank
kann, solange man nicht mit Objekten arbeitet (also ohne Verwendung des
Heaps). Statt dessen sollte man nur Arrays und Schleifen verwenden
Es ist dir schon klar, dass auch Arrays auf dem Heap angelegt werden?
Post by Ulrich Frank
z.B. Parser
Einen Parser nur mit Arrays und Schleifen bauen zu wollen, halte ich für
ausgemachten Blödsinn. Die meisten Parser (in Java) sind langsam (ich
denke da z.B. an XML-Parser) weil die Leute Stringverarbeitung nicht im
Griff haben. Nun könnte man natürlich Strings als Arrays von Zeichen
auffassen und tatsächlich wäre eine durchaus denkbare Optimierung, statt
mit java.lang.String direkt auf char-Arrays zu arbeiten. Der
Eclipse-Java-Compiler macht dies z.B..

In Java musst du übrigens bedenken, dass alle Array-Zugriffe eine
Indexprüfung beinhalten, sodass Zugriffe auf Arrays teurer sind als
Zugriffe auf Exemplarvariablen von Objekten. Klare Schleifenstrukturen
helfen aber der VM, die Indexprüfungen wegzuoptimieren. Daher bringt
inverse iterieren wenig und ist möglicherweise sogar schädlich für die
Performance.
Post by Ulrich Frank
Als nächstes dachte ich mir - "musst du mal nachlesen". Ich habe auch
ziemlich viele Seiten gefunden, die teilweise aber leider sehr alt
(beziehen sich auf Java 1.1, 1.2, 1.3) sind und inzwischen ist der Java
Compiler auch so aufgebaut, dass er viele Optimierungen selbst
vornimmt.
Korrekt. Vergiss eigentlich alles, was zu Java kleiner 5 geschrieben
wurde. Der größte Teil sind unhaltbaren Mythen.
Post by Ulrich Frank
Kennt ihr eine gute (aktuelle, für Java 1.5 sinnvolle Optimierungen)
Site oder ein Buch, in dem dieses Thema behandelt wird?
Die Hersteller machen zum Teil ein Geheimnis aus den
Optimierungsmöglichkeiten der VMs. Bei Sun könntest du dir aber den
Quelltext der VM anschauen. Ansonsten würde ich einige technical papers
als Grundlage empfehlen. Recht abgefahren, aber interessiert ist dies
http://research.sun.com/self/compiler.html als Grundlage für die
Hotspot-VM. Sie wurde über den Umweg der Animorphic VM aus der Self-VM
entwickelt. JavaOne-Paper sind auch eine gute Quelle für aktuelle
Informationen.
--
Stefan Matthias Aust // Ergo bibamus, ne sitiamus, vas repleamus!
Marcus Woletz
2006-05-20 16:16:10 UTC
Permalink
Hallo Ulrich,
Post by Ulrich Frank
Hallo NG,
ich habe eine Frage bzgl. der Effizienz von Java. Und zwar habe ich
gehört, dass Java durchaus mit C oder C++ in Sachen Laufzeit mithalten
kann, solange man nicht mit Objekten arbeitet (also ohne Verwendung des
Schmarrn! Selbsverständlich kann Java in Sachen Laufzeiteffizienz auch
bei OOP mit C++ mithalten. Was für eine grauenhafte Vorstellung, wegen
eines solchen Optimierungswahns auf OOP zu verzichten.

[...]
Post by Ulrich Frank
verwenden sollte, wenn man auch mit Objekten arbeiten will. Aber zur
Performanzsteigerung kann man die rechenintensiven Aufgaben optimieren
und den Rest (GUI) mittels OO Konzepten lösen ;)
Also bei einer größeren Optimierungsaufgabe z.B. würde ich auch eher
auf double-Arrays arbeiten wollen als auf Double-Arrays. Das ist
allerdings nur ein Bauchgefühl, denn evtl. optimieren da aktuelle
Compiler in der 1.5er-Version wegen autoboxing auch schon entsprechend.
(Nein ich habe autoboxing/-unboxing noch nicht verwendet ;-)

[...]
Post by Ulrich Frank
Beispiel: Hat man eine for-Schleife "for (int i = 0; i < 10000; i++)
{}" dann habe ich gelesen, dass man in so einem Fall nicht von 0 bis
10000 hoch zählen soll, sondern von 10000 runter bis 0. Warum? Weil
die Abbruchbedingung der Schleife ein Vergleich ist und der Vergleich
mit 0 schneller behandelt wird als der Vergleich mit (hier) 10000.
Also: for (int i = 9999; i >= 0; i--)
Zum Vergleich: Jetzt stelle dir bitte mal vor, du sitzt im ICE. Der hat
so, schätze ich mal als Hausnummer, 10000PS. Nun kommt jemand auf die
Idee, die Effizienz des ICE dadurch zu steigern, indem in den Toiletten
"normale" Glühlampen gegen "Energiesparlampen" ausgetauscht werden.
Würdest du das für den richtigen Ansatz halten?

Mache doch einfach mal einige einfache Performance-Messungen selbst,
dann bekommst du schnell ein Gefühl dafür, was geht und was nicht.
Und du wirst schnell feststellen, dass Schleifen auch in
Vorwärtszählrichtung hinreichend schnell sind ;-) Denn normalerweise
will man ja in den Schleifen auch irgend was machen. Die existieren ja
nicht zum Selbstzweck.
Post by Ulrich Frank
Stimmt das? Übernimmt der Compiler so eine Optimierung?
Kennt ihr eine gute (aktuelle, für Java 1.5 sinnvolle Optimierungen)
Site oder ein Buch, in dem dieses Thema behandelt wird?
Die besten Optimierungen sind:

1.) gesunder Menschenverstand (ist wirklich ernst gemeint!)
2.) grundlegende Kenntnisse der Informatik/Datenstrukturen/Algorithmen.
Wer immer nur mit brute-force bzw. naiven Algorithmen arbeitet, wird
kaum effiziente Programm implementieren (auch wenn brute-force
manchmal die einzige Möglichkeit darstellt ;-)
3.) ein grundlegendes Verständnis über die Laufzeitumgebung der
verwendeten Programmiersprache.
Post by Ulrich Frank
Danke und Grüße,
Uli
Also: sei stets auf der Suche nach den für deinen jeweiligen
Anwendungsfall geeigneten Datenstrukturen und Algorithmen,
habe viel Spaß beim Programmieren in Java und mache dir nur Gedanken um
die Optimierung, wenn es wirklich mal klemmen sollte!


ciao


Marcus
Holger Hoffstaette
2006-05-20 16:27:07 UTC
Permalink
Post by Marcus Woletz
1.) gesunder Menschenverstand (ist wirklich ernst gemeint!)
Jetzt übertreibst Du aber! Jobsicherheit und frickeln ist viel wichtiger!
Post by Marcus Woletz
2.) grundlegende Kenntnisse der Informatik/Datenstrukturen/Algorithmen.
"Für so Akademikerkram haben wir hier keine Zeit!"
-- Zitat eines Kunden

Es ist alles viel schlimmer als man denkt. Immer.

-h
Wanja Gayk
2006-05-22 13:27:30 UTC
Permalink
Post by Holger Hoffstaette
Post by Marcus Woletz
2.) grundlegende Kenntnisse der Informatik/Datenstrukturen/Algorithmen.
"Für so Akademikerkram haben wir hier keine Zeit!"
-- Zitat eines Kunden
Alle Mitarbeiter feuern senkt die Personalkosten auf null. Dann ist das
Unternehmen wieder profitabel.
Gut, die Lösung könnte problematisch sein, aber das ist Akademikerkram,
dafür hat der Kunde ja keine Zeit.

Gute Nacht.
Der Letzte macht das Licht aus.

Gruß,
-Wanja-
--
"Gewisse Schriftsteller sagen von ihren Werken immer: 'Mein Buch, mein
Kommentar, meine Geschichte'. [..] Es wäre besser, wenn sie sagten:
'unser Buch, unser Kommentar, unsere Geschichte'; wenn man bedenkt, dass
das Gute darin mehr von anderen ist als von ihnen." [Blaise Pascal]
Jochen Theodorou
2006-05-20 19:28:23 UTC
Permalink
Post by Ulrich Frank
Hallo NG,
ich habe eine Frage bzgl. der Effizienz von Java. Und zwar habe ich
gehört, dass Java durchaus mit C oder C++ in Sachen Laufzeit mithalten
kann, solange man nicht mit Objekten arbeitet (also ohne Verwendung des
Heaps). Statt dessen sollte man nur Arrays und Schleifen verwenden (die
Verwendung bezieht sich natürlich auf rechenintensive Aufgaben, die in
Model Klassen erledigt werden sollen, z.B. Parser oder
Matrixmultiplikation. Es ist klar, dass man eine OO Sprache nur
verwenden sollte, wenn man auch mit Objekten arbeiten will. Aber zur
Performanzsteigerung kann man die rechenintensiven Aufgaben optimieren
und den Rest (GUI) mittels OO Konzepten lösen ;)
Meinungen?
Also erstmal... nachdem was ich weiss ist das OO von C++ sehr langsam.
ein OO Programm in Java kann durchaus schneller sein als OO Programm in
C++ und zwar um so mehr, je mehr OOP darin vorkommt. Damit lehne ich
mich natürlich weit aus dem Fenster, aber ich denke dass der Ansatz auf
OOP verzichten zu wollen nur um effizienter zu sein bei Java einfach
falsch ist. Das ist bestimmt eine Legende aus Zeiten von C vs. C++, weil
in C++ die Methodenaufrufe via OO relativ langsam sind. Kann man dort
natürlich auch einfach beseitigen indem man die Funktionen direkt
aufruft bzw. als Pointer übergibt usw... Dann landet m,an bei dem, was
ich gerne C(++) nenne, das ist ein C Programm in C++ geschrieben. Und
deshalb ist sowas für mich auch kein C++ ;)

Was in Java davon bleibt ist zu versuchen die Anzhal der Objekte klein
zu halten. Früher hat man dafür Pools benutzt, aber dann kamen neue
Javaversionen heraus und so mancher Pool war langsamer als neue Objekte
zu erzeugen.

Es gab hier mal auch einen Thread indem jeamand meinte, dass statische
Methoden in Java schneller seien als virtuelle Methoden.. stimmt nicht,
das habe ich durch mehrere Messungen an meinem Rechner "bewiesen". Mal
waren die statischen schneller, mal die virtuellen, hängt ganz von der
Anzahl der Methodenaufrufe ab.

Das es gut ist die Erzeugung von Objekten zu vermeiden, das ist
allerdings immernoch meine Meinung. Allerdings nicht wenn man statt
dessen Pools benutzt, sondern wenn man wirklich etwas einsparen kann.
Und da kommen die wirklichen Optimierungen, die auf allen Prozessoren
und allen VMs funktionieren. Wenn du signifikant Schleifendurchläufe
einsparen kannst, dann wird dein Programm schneller. Wenn du der GC
weniger Arbeit gibst kann das schneller werden, aber nur wenn der GC nie
Zeit haben wird und der SPeicher knapp ist... usw.. Im Endeffekt sparst
du nur, wenn du den Algorithmus konzeptionell verbesserst. Wenn du aus
einem O(n²) einen O(nlogn) Algorithmus amchen kannst, dann ist er
wahrscheinlich schneller...

Aber selbst hier kommt es auf die Konstanten an. Bei wenigen Durchläufen
kann der O(n²) Algorithmus nämlich trotzdem schneller sein.. z.B. bei n=
1000, log = lg, c1=1, c2=1000... damit aslo der O(n²) = c1*n*2 =
1000000, der O(nlogn) = 3000000. Also ist der O(nlogn) algorithmus 3x
langsamer... rein formal betrachtet natürlich. In der Praxis würde ich
sagen: probieren, fertig.

Ein anderes Beispiel vielleicht.. Ich weiss nicht bo due Groovy kennst,
das ist eine alternative Programmiersprache für die JVM. Jedenfalls ist
Groovy derzeit noch etwa 8x langsamer als normales Java. Allerdings
bietet Groovy viele Konzepte, die Java nicht hat, man kann sich daher
mehr auf den Code konzentrieren. Und so hat einer zum Beipsiel einen
Algorithmus für die Bildverarbeitung gesucht und hat das in Groovy
gemacht. War natürlich langsam, aber er konnte erstmal den Algorithmus
verbessern und korrigieren und hat ihn dann ihn dann nach Java portiert.
Mit dem Erfolg dass er in der Hälfte der vorgesehenen Zeit fertig war
mit dem Grundentwurf des Algorithmus und die andere Hälfte auf
Optimierungen verwenden könnte.

Noch eine Geschichte vielleicht... früher hat man geglaubt alle
Performanceprobleme liessen sich durch JNI lösen. Immerhin kann man so
C-Code schreiben. Allerdings sind Aufrufe von JNI auch nicht die
schnellsten und in der Zwischenzeit hatte sich Java sehr an C
angenähert. Damit war JNI "plötzlich" oft langsamer geworden.. wieder
eine Optimierung die sich am Ende als Krücke herausgestellt hat.

Wenn du optimieren willst,d ann musst du da tatsächlich für alle
relevanten Plattformen tun, und zwar praktisch. Un mit Plattform meine
ich hier eine belibige Kombination aus Prozessor, OS und VM... das gibt
eine nette Menge an Möglichkeiten.

[...]
Post by Ulrich Frank
Stimmt das? Übernimmt der Compiler so eine Optimierung?
zu viele Optimierungen erweisen sich manchmal als kontraproduktiv. Man
sollte nciht vergessend ass Java eigentlich 2stuffig compiliert wird,
einmal vom normalen Compiler und dann nochmal vom JIT. Und was der JIT
macht, dass kann sehr unterschiedlich sein.. auch wann er das macht. Das
ist quasi ein blinder Fleck bei den Optimierungsmöglichkeiten. Deswegen
ist auch der rpaktische Test das einzig wirklich brauchbare neben einer
konzeptionellen Verbesserung unter Berücksichtigung der Konstanten.

Gruss theo
Hubert Schmid
2006-05-21 10:22:33 UTC
Permalink
Post by Jochen Theodorou
Post by Ulrich Frank
ich habe eine Frage bzgl. der Effizienz von Java. Und zwar habe ich
gehört, dass Java durchaus mit C oder C++ in Sachen Laufzeit
mithalten kann, solange man nicht mit Objekten arbeitet [..].
Also erstmal... nachdem was ich weiss ist das OO von C++ sehr
langsam. ein OO Programm in Java kann durchaus schneller sein als OO
Programm in C++ und zwar um so mehr, je mehr OOP darin vorkommt.
Ich denke auch, dass objektorientierter Code in C++ langsamer ist als
in Java. Ich vermute aber, dass der OP etwas anderes sagen wollte,
denn schließlich unterstützt C++ nicht nur objektorientiertes
Programmieren, sondern im Gegensatz zu Java auch Datenabstraktion und
generisches Programmieren.

Der OP meinte vermutlich, dass es Aufgaben gibt, für die eine
natürliche Lösung in C++ deutlich schneller als eine natürliche Lösung
in Java ist. Und dem kann ich mich nur anschliessen.

Ein bekanntes Beispiel ist das teure Kopieren von Objekten, wenn man
nur einen Wert kopieren will, wie beispielsweise im folgenden Code:

class Dimension {
public Dimension(int width, int height) {
this.width = width;
this.height = height;
}
public Dimension(Dimension rhs) {
this(rhs.width, rhs.height);
}
private int width;
private int height;
}

class Component {
public Component(Dimension size) {
this.size = new Dimension(size);
}
public Dimension getSize() {
return new Dimension(size);
}
private Dimension size;
}

Ich habe damit einen kleinen Test gemacht. In C++ wird statt dem
Objekt nur ein Wert kopiert. Der entsprechende C++-Code sieht etwa so
aus:

class Dimension
{
public:
Dimension(int width_, int height_)
: width(width_), height(height_)
{ }
private:
int width;
int height;
};

class Component
{
public:
explicit Component(const Dimension& size_)
: size(size_)
{ }
Dimension getSize()
{
return size;
}
private:
Dimension size;
};

In meinem Test war das C++-Programm 20mal schneller als das
Java-Programm. Ich finde, auch Java-Entwickler sollten erkennen, dass
Java nicht für jede Aufgabe die beste Wahl ist.

Gruß, Hubert
Ralf Ullrich
2006-05-21 10:44:27 UTC
Permalink
Post by Hubert Schmid
In meinem Test war das C++-Programm 20mal schneller als das
Java-Programm. Ich finde, auch Java-Entwickler sollten erkennen, dass
Java nicht für jede Aufgabe die beste Wahl ist.
Wie hast du denn deinen Test aufgebaut?

Microbenchmarks taugen nicht um Performance einer Java Laufzeitumgebung zu
messen.

cu
Hubert Schmid
2006-05-21 19:23:54 UTC
Permalink
Post by Ralf Ullrich
Post by Hubert Schmid
In meinem Test war das C++-Programm 20mal schneller als das
Java-Programm. Ich finde, auch Java-Entwickler sollten erkennen,
dass Java nicht für jede Aufgabe die beste Wahl ist.
Wie hast du denn deinen Test aufgebaut?
Microbenchmarks taugen nicht um Performance einer Java
Laufzeitumgebung zu messen.
Ich weiß etwa, wie ein JIT arbeitet und entsprechend habe ich das
Java-Programm geschrieben. Du kannst das aber gern selbst prüfen. Hier
ist der Java-Code:


public final class Test {

public static void main(String[] args) {
Component component = new Component(new Dimension(1, 2));
Component[] components = new Component[100000];
for (int i = 0; i < components.length; ++i) {
components[i] = component;
}
Dimension result = new Dimension();
for (int i = 0; i < 10000; ++i) {
Dimension size = sum(components);
result.width += size.width;
result.height += size.height;
}
}

private static Dimension sum(Component[] components) {
Dimension result = new Dimension();
for (Component component : components) {
Dimension size = component.getSize();
result.width += size.width;
result.height += size.height;
}
return result;
}

}

class Dimension {
public Dimension() {
this(0, 0);
}
public Dimension(int width, int height) {
this.width = width;
this.height = height;
}
public Dimension(Dimension rhs) {
this(rhs.width, rhs.height);
}
public int width;
public int height;
}

class Component {
public Component(Dimension size) {
this.size = size;
}
Dimension getSize() {
return new Dimension(size);
}
private Dimension size;
}
Ralf Ullrich
2006-05-21 20:48:07 UTC
Permalink
Post by Hubert Schmid
Post by Ralf Ullrich
Post by Hubert Schmid
In meinem Test war das C++-Programm 20mal schneller als das
Java-Programm. Ich finde, auch Java-Entwickler sollten erkennen,
dass Java nicht für jede Aufgabe die beste Wahl ist.
Wie hast du denn deinen Test aufgebaut?
Microbenchmarks taugen nicht um Performance einer Java
Laufzeitumgebung zu messen.
Ich weiß etwa, wie ein JIT arbeitet und entsprechend habe ich das
Java-Programm geschrieben. Du kannst das aber gern selbst prüfen.
Naja, offensichtlich nicht. Dein Test ist immer noch ein Micro-Benchmark,
entsprechend wenig aussagekräftig sind die Messungen.
Post by Hubert Schmid
Component[] components = new Component[100000];
Wenn du dein C++ Programm ähnlich aufgebaut hast, dann wäre das AFAIK die
einzige Zeile, bei der für deine Components Speicher alloziert wird.
Ziemlich unfairer Vergleich, wenn du in C++ nicht ebenfalls new
verwendest. Aber das haben ja schon andere gesagt.

Kommt hinzu, dass ein Java-Programmierer das Programm niemals so schreiben
würde.

Hier eine Version, wie sie eher einem Java-Programmierer aus den Fingern
fließen könnte:

package de.jnana.dclj.speed;

import java.util.Arrays;

public final class TestJava {

static class Dimension {
public int width;

public int height;

public Dimension() {
}

public Dimension(int width, int height) {
this.width = width;
this.height = height;
}

public Dimension(Dimension rhs) {
this.width = rhs.width;
this.height = rhs.height;
}

public void add(Dimension other) {
this.width += other.width;
this.height += other.height;
}

}

static class Component {
public Component(Dimension size) {
this.size = size;
}

Dimension getSize() {
return new Dimension(size);
}

private Dimension size;

public void summarizeTo(Dimension sum) {
sum.add(size);
}
}

public static void main(String[] args) {
long start = System.currentTimeMillis();
Component component = new Component(new Dimension(1, 2));
Component[] components = new Component[100000];
Arrays.fill(components, component);
Dimension result = new Dimension();
for (int i = 0; i < 10000; ++i) {
result.add(sum(components));
}
long duration = System.currentTimeMillis() - start;
System.out.println(duration + "ms");
}

private static Dimension sum(Component[] components) {
Dimension sum = new Dimension();
for (Component component : components) {
component.summarizeTo(sum);
}
return sum;
}

}

Obwohl diese Version noch immer nicht alle Verbesserungen macht, die mir
einfallen würden, ist sie auf meinem Rechner bereits etwa 8 mal schneller
als deine. Damit blieben von deinen "C++ ist 20mal schneller" gerade mal
noch "C++ ist zweieinhalb mal schneller". (Und das obwohl Java new
verwendet und dein C++ Programm nicht!)

Ich bin mir sicher, würde man daraus einen vollwertigen Benchmark machen
und durchgängig einen Java-Programmierstil anwenden (ebenso wie man bei
C++ gerne einen C++ Programmierstil anwenden darf), dann schrumpft das
weiter auf die üblichen "C++ ist nur knapp schneller als Java".

Um dich leicht abgewandelt zu zitieren: Ich finde, auch C++-Entwickler
sollten erkennen, dass Java nicht so langsam ist, wie man gemeinhin glaubt.

cu
Hubert Schmid
2006-05-22 19:07:02 UTC
Permalink
Post by Ralf Ullrich
Post by Hubert Schmid
Post by Ralf Ullrich
Microbenchmarks taugen nicht um Performance einer Java
Laufzeitumgebung zu messen.
Ich weiß etwa, wie ein JIT arbeitet und entsprechend habe ich das
Java-Programm geschrieben. Du kannst das aber gern selbst prüfen.
Naja, offensichtlich nicht.
Auf was bezieht sich dieses "offensichtlich nicht"?
Post by Ralf Ullrich
Dein Test ist immer noch ein Micro-Benchmark, entsprechend wenig
aussagekräftig sind die Messungen.
Bitte erkläre, warum die Messungen nicht aussagekräftig sind.
Post by Ralf Ullrich
Post by Hubert Schmid
Component[] components = new Component[100000];
Wenn du dein C++ Programm ähnlich aufgebaut hast, dann wäre das
AFAIK die einzige Zeile, bei der für deine Components Speicher
alloziert wird. Ziemlich unfairer Vergleich, wenn du in C++ nicht
ebenfalls new verwendest. Aber das haben ja schon andere gesagt.
Kannst du das bitte erklären? Diese Zeile wird nur einmal ausgeführt
und es wird nur eine einzige Component und ein einziges Array
erzeugt. Ich sehe nicht, was hier unfair sein könnte. Mal abgesehen
davon, dass der C++-Code sehr ähnlich ist:

typedef std::vector<Component*> Components;

Component component(Dimension(1, 2));
Components components(100000, &component);
Post by Ralf Ullrich
Kommt hinzu, dass ein Java-Programmierer das Programm niemals so
schreiben würde.
Willst du damit sagen, dass ich kein Java-Programmierer bin? Und wer
hat die Funktion java.awt.Component.getSize() geschrieben? War das
auch kein Java-Programmierer?

Auch in Java müssen Objekte häufig kopiert werden. Es gibt viele
Entwickler, die die Kopien an wichtigen Stellen nicht machen, -
möglicherweise aus Bequemlichkeit, aus Unwissenheit oder zur
Verbessung der Laufzeit. Ein Beispiel ist dein Konstruktor von
Component, in dem die Kopie fehlt:

public Component(Dimension size) {
this.size = size;
}
Post by Ralf Ullrich
Hier eine Version, wie sie eher einem Java-Programmierer aus den
[Quelltext bei dem die Kopie der Klasse Dimension eliminiert wurde.]
Post by Ralf Ullrich
Obwohl diese Version noch immer nicht alle Verbesserungen macht, die
mir einfallen würden, ist sie auf meinem Rechner bereits etwa 8 mal
schneller als deine.
Ich versuche das zusammenzufassen: Ich schrieb, dass das Kopieren von
Objekten in Java teuer ist, wenn man nur einen Wert kopieren
will. Dazu habe ich einen Vergleich mit C++ gemacht. Jetzt behauptest
du, dass das nicht wahr ist. Das belegst du, indem du in dem Beispiel
die Kopien eliminiert hast, wodurch das Programmm 8mal schneller wird.

Habe ich das richtig zusammengefasst? Dann kann ich nur sehen, dass
das meine Aussage nur unterstützt, dass Kopien in Java teuer sind.
Post by Ralf Ullrich
Um dich leicht abgewandelt zu zitieren: Ich finde, auch
C++-Entwickler sollten erkennen, dass Java nicht so langsam ist, wie
man gemeinhin glaubt.
Dem stimme ich zu. Ich habe auch nichts anderes behauptet.

Gruß, Hubert
Ralf Ullrich
2006-05-22 19:51:38 UTC
Permalink
Da sachliche Korrekturen bei dir ja eh nicht anzukommen scheinen, und sich
so nur ein Streit entwickeln kann, beschränke ich mal auf eine
Richtigstellung.
Post by Hubert Schmid
Auch in Java müssen Objekte häufig kopiert werden. Es gibt viele
Entwickler, die die Kopien an wichtigen Stellen nicht machen, -
möglicherweise aus Bequemlichkeit, aus Unwissenheit oder zur
Verbessung der Laufzeit. Ein Beispiel ist dein Konstruktor von
public Component(Dimension size) {
this.size = size;
}
Das ist _DEIN_ Code, ich habe ihn nur kopiert.

cu
Ralf Ullrich
2006-05-22 20:45:30 UTC
Permalink
Ok, mein letztes Posting war vielleicht doch etwas kurz. Ich erklär dir
mal, warum ich keine Lust habe, mit dir weiter über Java/C++ -Performance
zu streiten.
Post by Hubert Schmid
Post by Ralf Ullrich
Post by Hubert Schmid
Post by Ralf Ullrich
Microbenchmarks taugen nicht um Performance einer Java
Laufzeitumgebung zu messen.
Ich weiß etwa, wie ein JIT arbeitet und entsprechend habe ich das
Java-Programm geschrieben. Du kannst das aber gern selbst prüfen.
Naja, offensichtlich nicht.
Auf was bezieht sich dieses "offensichtlich nicht"?
Ich sage dir, ich will keinen MicroBenchmark sehen, du präsentierst einen
MicroBenchmark.
Post by Hubert Schmid
Post by Ralf Ullrich
Dein Test ist immer noch ein Micro-Benchmark, entsprechend wenig
aussagekräftig sind die Messungen.
Bitte erkläre, warum die Messungen nicht aussagekräftig sind.
Weil sie nur ein klitzekleines Feature einer spezifischen
Sprach-IMPLEMENTATION testen. Wenn ich dein Programm auf meiner
super-optimierenden Muckefuck-VM laufen lasse, ist die Laufzeit unterhalb
der Meßgrenze. Sagt das dann was über die Sprache aus?

Das wäre ungefähr dasselbe, als wenn du sagst: AMD imul ist zwei Takte
schneller als Intel imul. Ist AMD damit der schnellere/bessere Prozessor?
Post by Hubert Schmid
Willst du damit sagen, dass ich kein Java-Programmierer bin? Und wer
hat die Funktion java.awt.Component.getSize() geschrieben? War das
auch kein Java-Programmierer?
Das war derjenige, der für Java 1.1 einen Ersatz für "deprecated public
Dimension size()" liefern musste.

Der "richtige" Java Programmierer hatte schon für Java 1.0 die Methode
"public Dimension getSize(Dimension rv)" bereitgestellt.

Für Java 1.2 aka Java 2 wurden dann die zu bevorzugenden Alternativen
"public int getHeight()", "public int getWidth()" hinzugefügt.


Ich bin mir sicher, bei "C++ 1.0" hatten auch noch nicht alle raus, wie
man damit effiziente Programme schreibt. Aber seit Java 2 ist es immerhin
Best Practice eine API so aufzubauen, dass sie auf "Sicherheitskopien"
möglichst verzichtet.

Zwei leicht zu inlinende Methodenaufrufe, sind eben deutlich schneller als
eine Heap-Allocation.
Post by Hubert Schmid
Auch in Java müssen Objekte häufig kopiert werden.
Nein, müssen sie nicht. Im Gegenteil: I.d.R. ist es besser den Algorithmus
auf Immutable-Objekte umzustellen und dies ggf. durch entsprechende
Interfaces abzusichern.

Java erinnert an die Kosten einer Kopie, weil ich immer explizit ein new
schreiben muss, während C++ Objekte teilweise automatisch kopiert. (Nach
meiner lange Jahre zurückliegende C++ Erfahrung ist es unter C++ sogar
schwieriger die automatischen Kopien zu vermeiden, als unter Java, die
wirklich notwendigen einzufügen.

Wenn mich also Java daran erinnert, meinen Code nochmal zu überdenken,
weil ich viel zu oft "new" schreiben musste, dann ist das für mich eher
ein Vorteil, denn ein Nachteil.

Wenn bei C++ diese Kopien nicht so viel kosten wie bei Java, dann
ermöglicht das nur, ein eigentlich schlechtes Design durchzumogeln, weil
es nicht weiter auffällt.


So nun noch einige andere Absätze von dir, die mir wirklich die Lust
Post by Hubert Schmid
Wahrscheinlich ist das C++-Programm genauso langsam wie das
Java-Programm, wenn man im C++-Programm ebenfalls die Objekte mit new
erzeugen würde. Nur warum sollte man das in C++ tun?
Und warum sollte man in Java unnötige Kopien erstellen?

Ich meine du verzichtest in C++ freimütig aufs new weil du weißt, dass es
evtl. langsam ist und kritisierst es dann, wenn man in Java auf Kopien
verzichtet, nur weil sie langsam sind?
Post by Hubert Schmid
Post by Ralf Ullrich
Du hast ein funktionell identisches Programm in C++ und Java
geschrieben, jedoch kein identisch aufgebautes.
Darum ging es ja genau. Warum sollte ich in C++ denn Java
programmieren?
OK, aber warum sollte ich dann in meinem funktionell identischen Java
Programm C++ programmieren? Genau das verlangst du aber von mir, wenn du
meine Version wegen der eliminierten Kopien verwirfst.



Aber vielleicht können wir ja wenigstens folgendes ohne weiteren Kommentar
Post by Hubert Schmid
Es geht mir nicht darum, Java oder C++ gewinnen zu lassen. Ich weiß,
dass beide Sprachen ihre Stärken haben. Und für beide Sprachen gibt
Systeme, bei denen die eine Sprache gegenüber der anderen deutliche
Vorteile hat.
Genau. C++ ist eine Nuance schneller, Java ist wesentlich einfacher (und
zumindest für mich klarer im Ausdruck, aber das sehen selbst hier in dclj
viele anders).


cu
Jochen Theodorou
2006-05-21 12:20:04 UTC
Permalink
Post by Hubert Schmid
Post by Jochen Theodorou
Post by Ulrich Frank
ich habe eine Frage bzgl. der Effizienz von Java. Und zwar habe ich
gehört, dass Java durchaus mit C oder C++ in Sachen Laufzeit
mithalten kann, solange man nicht mit Objekten arbeitet [..].
Also erstmal... nachdem was ich weiss ist das OO von C++ sehr
langsam. ein OO Programm in Java kann durchaus schneller sein als OO
Programm in C++ und zwar um so mehr, je mehr OOP darin vorkommt.
Ich denke auch, dass objektorientierter Code in C++ langsamer ist als
in Java.
Meine C++ä-Zeiten sind etwas länger her, daher hast du hoffentlich
gleich ein wenig Geduld mit mir.

[...]
Post by Hubert Schmid
explicit Component(const Dimension& size_)
: size(size_)
{ }
Dimension getSize()
{
return size;
}
Dimension size;
};
Also wenn ich das noch richtig weiss, dann wird dimension hier kopiert,
ja. Allerdings ist ein Objekt mit "new" anzulegen nicht das gleiche.
Tatsächlich gibt es kein Äquivalent dazu in Java. Wenn du auch in C++
den Konstruktor durchläufst, dann sieht die Sache schon wieder etwas
anders aus. Ausserdem... Ein Objekt enthält ja oft Pointer auf weitere
Objekte, diese werden dabei ja auch kopiert, wenn ich dort aber was
ändere, dann ist das für alle Kopien eine Änderung.. oh wie war denn die
Syntax... x=a; a->b->onlyOnceOrFail(); x->b->onlyOnceOrFail()... naja,
soll nciht zu 100% korrekt sein, soll nur meinen Gedankengang etwas
illustrieren. JAva hat keine Structs und dementsprechend dieses Problem
hier. Ja
Post by Hubert Schmid
In meinem Test war das C++-Programm 20mal schneller als das
Java-Programm. Ich finde, auch Java-Entwickler sollten erkennen, dass
Java nicht für jede Aufgabe die beste Wahl ist.
stimmt. Allerdings... um so komplexer das Beispiel um so mehr kann Java
aufholen.

Gruss theo
Hubert Schmid
2006-05-21 19:59:18 UTC
Permalink
Post by Jochen Theodorou
Post by Hubert Schmid
explicit Component(const Dimension& size_)
: size(size_)
{ }
Dimension getSize()
{
return size;
}
Dimension size;
};
Also wenn ich das noch richtig weiss, dann wird dimension hier
kopiert, ja. Allerdings ist ein Objekt mit "new" anzulegen nicht das
gleiche. Tatsächlich gibt es kein Äquivalent dazu in Java. Wenn du
auch in C++ den Konstruktor durchläufst, dann sieht die Sache schon
wieder etwas anders aus.
Auch in C++ wird der Konstruktor ausgeführt. Es wird nur kein Speicher
auf dem Heap allokiert und wieder freigegeben.

Wahrscheinlich ist das C++-Programm genauso langsam wie das
Java-Programm, wenn man im C++-Programm ebenfalls die Objekte mit new
erzeugen würde. Nur warum sollte man das in C++ tun?
Post by Jochen Theodorou
Ausserdem... Ein Objekt enthält ja oft Pointer auf weitere Objekte,
diese werden dabei ja auch kopiert, wenn ich dort aber was ändere,
dann ist das für alle Kopien eine Änderung.. oh wie war denn die
Syntax... x=a; a->b->onlyOnceOrFail();
x->b->onlyOnceOrFail()... naja, soll nciht zu 100% korrekt sein, soll
nur meinen Gedankengang etwas illustrieren.
Ich verstehe nicht, was du mir damit sagen willst.
Post by Jochen Theodorou
Post by Hubert Schmid
In meinem Test war das C++-Programm 20mal schneller als das
Java-Programm. Ich finde, auch Java-Entwickler sollten erkennen,
dass Java nicht für jede Aufgabe die beste Wahl ist.
stimmt. Allerdings... um so komplexer das Beispiel um so mehr kann
Java aufholen.
Es gibt Systeme, bei denen C++ deutliche Vorteile gegenüber Java
hat. Insbesondere solche Systeme, bei denen nicht die CPU sondern der
Hauptspeicher die begrenzende Resource ist.

Gruß, Hubert
Thomas G. Liesner
2006-05-21 11:24:54 UTC
Permalink
Post by Hubert Schmid
Ich denke auch, dass objektorientierter Code in C++ langsamer ist als
in Java.
Warum sollte er?

So long,
Thomas G. Liesner
--
---------------- Neue Hamster-stable 2.1.0.11 seit 28.03.2006 -----------------
Ich suche eine neue Vollzeitarbeitsstelle als Softwareentwickler (Schwerpunkt
Windows) entweder im weiteren Umkreis von Münster (Westfalen) oder in Heim-
arbeit. Details: http://www.tglsoft.de <mailto:***@tglsoft.de>
Jochen Theodorou
2006-05-21 14:04:16 UTC
Permalink
Post by Thomas G. Liesner
Post by Hubert Schmid
Ich denke auch, dass objektorientierter Code in C++ langsamer ist als
in Java.
Warum sollte er?
das ist eine gute Frage, verschiedene Tests scheinen das zu beweisen...
Natürlich nur wenn man den Teil betrachtet, den C++ nicht mit C gleich
hat... da bleibt nur noch Klasse und das drum herum. Das eine virtueller
Methodenaufruf langsamer ist sollte klar sein, aber wesentlich
langsamer? Also um es mal so zu sagen: Ich weiss es nicht.

Gruss theo
Thomas G. Liesner
2006-05-21 14:28:32 UTC
Permalink
Post by Jochen Theodorou
das ist eine gute Frage, verschiedene Tests scheinen das zu beweisen...
Natürlich nur wenn man den Teil betrachtet, den C++ nicht mit C gleich
hat... da bleibt nur noch Klasse und das drum herum. Das eine virtueller
Methodenaufruf langsamer ist sollte klar sein, aber wesentlich
langsamer? Also um es mal so zu sagen: Ich weiss es nicht.
Ich kenne C++ fast nur von der Theorie, aber wenn ich sehe, daß dort
virtuelle Methoden nur bei Bedarf benutzt werden brauchen, Objekte auch
auf dem Stack erzeugt werden können mit automatischem Abräumen beim
Verlassen des Gültigkeitsbereichs, die Übergabevarianten bei Parametern
auch effiziente Möglichkeiten erlauben, die bei Java versperrt sind und
Templates durch automatisch generierte Klassen geregelt werden, kein
noch einmal zu kompilierender Bytecode, sondern direkter Maschinencode
generiert wird...

Dann kann es nach meinem Verständnis nur daran liegen, daß entweder die
konkrete Implementierung von C++-Compilern zu wünschen übrig läßt oder
der JIT-Compiler von Java durch Ausnutzung von prozessorspezifischen
Möglichkeiten uä inzwischen bessere Ergebnisse liefert als Code, der nur
allgemein für PCs als Ziel kompiliert wird.

So long,
Thomas G. Liesner
--
---------------- Neue Hamster-stable 2.1.0.11 seit 28.03.2006 -----------------
Ich suche eine neue Vollzeitarbeitsstelle als Softwareentwickler (Schwerpunkt
Windows) entweder im weiteren Umkreis von Münster (Westfalen) oder in Heim-
arbeit. Details: http://www.tglsoft.de <mailto:***@tglsoft.de>
Hubert Schmid
2006-05-21 19:34:00 UTC
Permalink
Post by Thomas G. Liesner
Post by Hubert Schmid
Ich denke auch, dass objektorientierter Code in C++ langsamer ist
als in Java.
Warum sollte er?
Ein JIT-Übersetzer hat einige Vorteile gegenüber einer statischen
Übersetzung, da zur Laufzeit mehr Information über das System
vorhanden ist. Der JIT-Übersetzer von Java setzt beispielsweise viele
virtuelle Methoden an der Aufrufstelle offen ein. Bei einer statischen
Übersetzung funktioniert das meistens nicht, da nur selten bekannt
ist, von welchem dynamischem Typ ein Objekt ist. Und mir ist keine
C++-Umgebung bekannt, die einen JIT-Übersetzer verwendet, woei das
wahrscheinlich irgendwann kommen wird.

Damit kann man leicht ein Beispiel konstruieren, bei dem das
Java-Programm 10mal schneller als das entsprechende C++-Programm
ausgeführt wird.

Gruß, Hubert
Marcus Woletz
2006-05-21 13:35:13 UTC
Permalink
Hallo Hubert,

Hubert Schmid schrieb:

[Beispielprogramm in Java und C++ gesnippt]
Post by Hubert Schmid
In meinem Test war das C++-Programm 20mal schneller als das
Java-Programm. Ich finde, auch Java-Entwickler sollten erkennen, dass
Java nicht für jede Aufgabe die beste Wahl ist.
Gruß, Hubert
Klar ist das dynamische Anfordern von Speicher teurer als das
setzen des Stapelzeigers auf einen neuen Wert ;-)
Sobald du jedoch in C++ auch "new" schreibst, kann es sogar
sein, dass das Java-Programm schneller wird.

Du hast ein funktionell identisches Programm in C++ und Java
geschrieben, jedoch kein identisch aufgebautes.

Wenn man mehr Objekte benötigt, wird man die selbstverständlich
auch in C++ dynamisch erzeugen. Und dann schrumpft der
Vorsprung von C++ drastisch.

OK, man darf nicht verschweigen, dass in C++ selbst dann,
wenn die Component-Objekte auf dem Heap angelegt werden,
nur eine Speicheranforderung notwendig ist, also ein Punkt an C++
In Java sind pro Component-Objekt zwei Anforderungen notwendig.
Mal sehen, vielleicht teste ich mal den Unterschied.

Ich möchte ehrlich sein: ich war immer überzeugt (auch durch die
vielen Aussagen, die im Netz dazu kursieren), dass Java wesentlich
langsamer ist als C++. Dies hat sich allerdings in eigenen Versuchen
nicht bestätigt. Und in der Praxis mache ich mir nur in ganz wenigen
Fällen Gedanken um eine effiziente Speicheranforderung.

OK, man kann sich natürlich die passenden Vergleichsprogramme so
zusammenbasteln, dass die Sprache gewinnt, die man gewinnen lassen
möchte. Ist halt wie mit Statistiken ;-)

ciao

Marcus
Hubert Schmid
2006-05-21 19:47:11 UTC
Permalink
Post by Marcus Woletz
[Beispielprogramm in Java und C++ gesnippt]
Post by Hubert Schmid
In meinem Test war das C++-Programm 20mal schneller als das
Java-Programm. Ich finde, auch Java-Entwickler sollten erkennen,
dass Java nicht für jede Aufgabe die beste Wahl ist. Gruß, Hubert
Klar ist das dynamische Anfordern von Speicher teurer als das setzen
des Stapelzeigers auf einen neuen Wert ;-) Sobald du jedoch in C++
auch "new" schreibst, kann es sogar sein, dass das Java-Programm
schneller wird.
Du hast ein funktionell identisches Programm in C++ und Java
geschrieben, jedoch kein identisch aufgebautes.
Darum ging es ja genau. Warum sollte ich in C++ denn Java
programmieren?
Post by Marcus Woletz
OK, man darf nicht verschweigen, dass in C++ selbst dann, wenn die
Component-Objekte auf dem Heap angelegt werden, [..]
Darum ging es überhaupt nicht. Es ging nur um das Kopieren einer
Datenstruktur, angelehnt an die Verwendung von java.awt.Dimension.
Post by Marcus Woletz
OK, man kann sich natürlich die passenden Vergleichsprogramme so
zusammenbasteln, dass die Sprache gewinnt, die man gewinnen lassen
möchte. Ist halt wie mit Statistiken ;-)
Es geht mir nicht darum, Java oder C++ gewinnen zu lassen. Ich weiß,
dass beide Sprachen ihre Stärken haben. Und für beide Sprachen gibt
Systeme, bei denen die eine Sprache gegenüber der anderen deutliche
Vorteile hat.

Gruß, Hubert
Lothar Kimmeringer
2006-05-30 22:13:14 UTC
Permalink
Post by Jochen Theodorou
Noch eine Geschichte vielleicht... früher hat man geglaubt alle
Performanceprobleme liessen sich durch JNI lösen. Immerhin kann man so
C-Code schreiben. Allerdings sind Aufrufe von JNI auch nicht die
schnellsten und in der Zwischenzeit hatte sich Java sehr an C
angenähert. Damit war JNI "plötzlich" oft langsamer geworden.. wieder
eine Optimierung die sich am Ende als Krücke herausgestellt hat.
Wobei wir da zeitlich vom Uebergang von Java 1.1 auf Java 1.2
sprechen. Da hat selbst SUN z.B. die bigint-Bibliothek die
von java.math.BigInteger fuer die Erzeugung von Primzahlen
verwendet wurde, durch entsprechenden Javacode ersetzt, der dann
schon damals genauso schnell lief, wie der Code ueber JNI in 1.1.

Leider sind die meissten Leute, die heute noch ueber die Lang-
samkeit von Java schwadronieren, geistig auf dem Stand von Java
1.1 stehengeblieben. Und das ist ja jetzt auch bald wieder
9 Jahre her.


Gruesse, Lothar
--
Lothar Kimmeringer E-Mail: ***@kimmeringer.de
PGP-encrypted mails preferred (Key-ID: 0x8BC3CD81)

Always remember: The answer is forty-two, there can only be wrong
questions!
Ulrich Frank
2006-05-23 14:31:33 UTC
Permalink
Hallo zusammen,

also erstmal danke für die viele Postings!! Hätte ja nicht gedacht,
dass das Thema auf solch eine Resonanz stößt.

Wie ich aus den Beiträgen herauslesen kann, gibt es doch einige
unterschiedliche Ansichten, aber ich fasse mal folgendes zusammen:

1) Es gibt (natürlich) keine allg. gültige Aussage, wie man am
effizientesten programmieren kann. Es kommt immer auf diverse Faktoren
an, die beachtet werden müssen. Solche Faktoren sind beispielsweise:
Programmiersprache, Zielplattform(en), Algorithmen, deren
Laufzeiteffizienz, Datenstrukturen ...

2) Trotzdem sollte man wie folgt vorgehen: erst denken, dann handeln
2a) Sauberer objektorientierter Entwurf + Umsetzung (Korrektheit der
Anwendung muss gesichert sein)
2b) Profiler anwerfen und HotSpots herausfinden und optimieren


Nichts desto trotz gibt es ein paar Dinge auf die man zwecks Effizienz
beim Implementieren achten sollte. Z.B. die Verwendung eines
StringBuilders/StringBuffers in einer Schleife die immer wieder den
selben String verändert (Vermeidung der Erzeugung von neuen Objekten
bei jedem Schleifendurchlauf). Solche Optimierungen würde mich schon
interessieren. Kennt dazu jemend eine gute Sammlung solcher Best
Practices?

Grüße und danke nochmal,
Uli
Michael Paap
2006-05-23 16:45:55 UTC
Permalink
Post by Ulrich Frank
Nichts desto trotz gibt es ein paar Dinge auf die man zwecks Effizienz
beim Implementieren achten sollte. Z.B. die Verwendung eines
StringBuilders/StringBuffers in einer Schleife die immer wieder den
selben String verändert (Vermeidung der Erzeugung von neuen Objekten
bei jedem Schleifendurchlauf). Solche Optimierungen würde mich schon
interessieren. Kennt dazu jemend eine gute Sammlung solcher Best
Practices?
Nicht speziell auf Effizienz zielend, aber z.B. den genannten Fall
behandelnd: "Addison-Wesley - Effective Java - Programming Language
Guide", http://java.sun.com/docs/books/effective

Gruß,
Michael
Lesen Sie weiter auf narkive:
Suchergebnisse für 'Java und Effizienz' (Newsgroups und Mailinglisten)
179
Antworten
Kein Programmiergenie würde Java wählen
gestartet 2004-07-29 20:34:48 UTC
de.comp.lang.java
49
Antworten
abstract und interface
gestartet 2004-12-28 15:46:18 UTC
de.comp.lang.java
14
Antworten
ODBC mit Simba und OOo
gestartet 2002-07-10 13:05:00 UTC
users@de.openoffice.org
7
Antworten
Java Server?
gestartet 2005-02-28 01:21:26 UTC
de.comp.lang.java
68
Antworten
Eigenschaften in Java
gestartet 2004-04-09 15:38:08 UTC
de.comp.lang.java
Suchergebnisse für 'Java und Effizienz' (Fragen und Antworten)
2
Antworten
Was ist der Unterschied zwischen Reaktant, überschüssigem Reaktanten und limitierendem Reaktanten in einer ausgeglichenen Gleichung?
gestartet 2017-09-06 05:36:40 UTC
chemie
7
Antworten
Wie kann ein ganzes Team wechseln und neue Jobs bei einem anderen Unternehmen finden?
gestartet 2017-01-01 05:03:26 UTC
arbeit
3
Antworten
Warum ist die Insel Java so besiedelt?
gestartet 2020-06-04 01:05:48 UTC
geschichte
21
Antworten
Lehren und Missverständnisse in Bezug auf Verschlüsselung und Kryptologie
gestartet 2011-02-20 01:25:34 UTC
sicherheit
3
Antworten
Java-IDE, die mit git kompatibel ist
gestartet 2014-02-05 23:55:03 UTC
softwareempfehlungen
Nicht verwandte, aber interessante Themen
6
Antworten
Was ist die beste JavaScript-Diagrammbibliothek, die in einer kommerziellen Webanwendung kostenlos verwendet werden kann?
gestartet 2014-10-27 11:30:10 UTC
6
Antworten
Free / Libre Open Source Q & A-Site-Software, Stack Exchange-Ersatz
gestartet 2015-04-01 15:18:33 UTC
5
Antworten
Ripping-Software für Audio-CDs unter Linux
gestartet 2014-11-27 15:07:11 UTC
6
Antworten
Software zum Zeichnen von Zustandsdiagrammen und ASM-Diagrammen?
gestartet 2014-06-06 13:31:38 UTC
5
Antworten
Ich möchte einen Programmierblog starten. Was soll ich verwenden?
gestartet 2014-06-10 10:13:11 UTC
Loading...