welche sprache als "ersatz" für c++

Da würde ich gerne einhaken:
Habt ihr Quellen über performantes Schreiben in Java? - Bücher/Seiten.
 
Eine paar Tipps hätte ich:
- Nach Möglichkeit StringBuffer anstatt String zu benutzen. Gerade beim Zusammensetzen von Strings macht das einen erheblichen Performanceunterschied.
- Mengen nicht direkt in Arrays abspeichern, sondern statt dessen ArrayList, Stack oder so was nehmen. Beim Hinzufügen oder Entfernen von Elementen ist das auf jeden Fall deutlich schneller.
- Beim Suchen die Menge anhand des Suchkriteriums vorsortieren, oder besser gleich in einer sortierten Datenstruktur abspeichern, wie z. B. Hashtable.

Im Großen und Ganzen ist es das auch schon.
Solche Tipps, wie möglichst wenig Funktionsaufrufe in einer Schleife kannst du getrost in die Tonne schmeissen.


Gruß Fabian
 
Naja. Es heißt hier, dass Java nicht langsamer ist, sondern dass es am falschen Programmieren liegt... Ich möchte mich als Java-Skeptiker auch gern überzeugen lassen.

Aber Einfügen in Arrays ist in jeder Sprache langsam... Vorsortieren macht auch ein C++-Programm schneller...

An String-Operationen allein wird's doch nicht liegen?

(Im übrigen habe ich prinzipiell nichts gegen langsamere Programme, wenn man sich dadurch Bequemlichkeit erkauft...)
 
nschum schrieb:
An String-Operationen allein wird's doch nicht liegen?

Strings sind in Java quasi Konstanten, sowas wie

String1="Guten Tag, "+String1;

definiert also eine Konstante um und ist wenig performant. Bei exzessiverem Gebrauch sollte man daher die dynamischen StringBuffer nehmen.
 
Danke, aber die paar Dinger kannte ich bereits.
Auf die Liste könnte man noch setzen, bei möglichkeiten temporäre Objekte benutzen, spart Speicher.
Mir geht es generell im Strategien speziell für Java, damit das bestmögliche an Performance/Speicher erzielt werden kann. Und da könnte ich mir ein schön gegliedertes Buch gut vorstellen. Nur das habe och noch nicht gefunden.
 
definiert also eine Konstante um und ist wenig performant. Bei exzessiverem Gebrauch sollte man daher die dynamischen StringBuffer nehmen.

Schon klar. Natürlich definiert man nicht eine Konstante um (wäre unlogisch), sondern eine neue... Aber eine der Stärken Javas soll doch die schnelle Objekt-Allokierung sein. Außerdem hat man in C erst mal das selbe Problem, wenn man nicht aufpasst. strcat ist sogar O(n).

Ich meinte auch eher: Viele Programme sind schon durch genau diese Operation im Durchsatz limitiert?
 
Zuletzt bearbeitet:
Strings sind in Java quasi Konstanten, sowas wie

String1="Guten Tag, "+String1;

definiert also eine Konstante um und ist wenig performant. Bei exzessiverem Gebrauch sollte man daher die dynamischen StringBuffer nehmen.
Das gleiche gibt es auch in Objective-C und da ist es ein Gerücht, dass dies ein schlechteres Laufzeitverhalten hat. Du hast als Overhead zwar die Objektallozierung, dafür sparst du Speicher und Kopierzeit. Da nämlich alle beteiligten Partner Konstanten sind, lässt sich das kacheln. Man muss nur ein paar Pointer auf die Backends hinbritzeln.

Ich halte es daher für zweifelhaft, dass das in Java "auf Dauer" langsamer ist. In Objective-C würde ich es in der Regel für schneller erachten, weil Swappng gespart wird. (Das Gegenteil gehört zu den großen Mythen.)
 
Ich halte es daher für zweifelhaft, dass das in Java "auf Dauer" langsamer ist.
Es ist um einige Größenordnungen langsamer.


Code:
java.util.Random rand = new java.util.Random();
String test = "";
StringBuilder test2 = new StringBuilder(test);
for( int i = 0; i<10000; i++) {
    //Zeitangabe, wenn auskommentiert:
    //test += String.valueOf(rand.nextInt()); // ca. 20 Sekunden
    //test2.append(String.valueOf(rand.nextInt())); // ca. 0 Sekunden
}
if(test2.length() > 0) test = test2.toString();
System.out.print(test.length());
Das lässt sich natürlich noch weiter treiben, mit 1 Mio Durchläufen ist das StringBuilder-Beispiel immer noch in < 1 Sekunde fertig, beim anderen habe ich keine Lust das abzuwarten.
 
Zuletzt bearbeitet:
Dein Beispiel reizt natürlich den worst-case aus, weil der String extrem lang wird (100kB).

Macht man im Inneren der Schleife:
Code:
test = "foobar1234567890123456789012345678901234567890";
test += String.valueOf(rand.nextInt());

ist es nicht merklich langsamer. Und das dürfte wesentlich näher am tagtäglichen Einsatz sein. Von daher halte ich es für unwahrscheinlich, dass dies ursächlich für die schlechtere Performance von Java-Programmen ist. Zumal man in C den selben "Fehler" machen kann.
 
Also sooo langsam ist Java nun auch nicht. Es gibt nur viele Java-Programmierer, die keine Ahnung haben, wie man Java programmiert ;)
Oha. So hab ich das doch gar nicht gemeint. Ich bin auch ein Gegner von „Java ist kack lahm“, aber afaik sind C und D doch meist etwas schneller (wobei man die aber auch langsamer bekommt als Java, wenn man nur schön scheiße programmiert *g*). Bei den meisten Anwendungen wird man aber keinen Unterschied spüren.
 
Es ist um einige Größenordnungen langsamer.


Code:
java.util.Random rand = new java.util.Random();
String test = "";
StringBuilder test2 = new StringBuilder(test);
for( int i = 0; i<10000; i++) {
    //Zeitangabe, wenn auskommentiert:
    //test += String.valueOf(rand.nextInt()); // ca. 20 Sekunden
    //test2.append(String.valueOf(rand.nextInt())); // ca. 0 Sekunden
}
if(test2.length() > 0) test = test2.toString();
System.out.print(test.length());
Das lässt sich natürlich noch weiter treiben, mit 1 Mio Durchläufen ist das StringBuilder-Beispiel immer noch in < 1 Sekunde fertig, beim anderen habe ich keine Lust das abzuwarten.
Schlecht implementiert, das darf nicht passieren. Beide Varianten müssen einen String erzeugen, beide "verschmelzen". append muss dazu die einzelnen Bytes kopieren, da es veränderlich ist und sich mit dem Werteobjekt keinen Speicher teilen darf. Das neue Objekt muss einfach zwei Zeiger in Kacheln kopieren. (Bei einer anständigen Implementierung.)

Es kann natürlich sein, dass append CoW nutzt. Dann würde das Laufzeitverhalten einfach auf den Zeitpunkt der Veränderung von test2 verschoben, was man bei dir nicht sieht.

+++

Mal als Graphik:
Hat man nur Immutables, dann reicht das Kopieren von Zeigern aus:
http://www.cocoading.de/webspace/Concat.png

Hat man ein verdorbenes Ei, dann muss kopiert werden:
http://www.cocoading.de/webspace/Append.png

Man kann das freilich mit CoW abmildern, weil dann zunächst auch nur eine Zeigerkopie erforderlich ist, erst bei weiteren Veränderungen das Auflösen zur Kopie.

Wäre eigentlich einer längeren Untersuchung wert …
 
Zuletzt bearbeitet:
angemawad schrieb:
Schlecht implementiert, das darf nicht passieren. Beide Varianten müssen einen String erzeugen, beide "verschmelzen". append muss dazu die einzelnen Bytes kopieren, da es veränderlich ist und sich mit dem Werteobjekt keinen Speicher teilen darf. Das neue Objekt muss einfach zwei Zeiger in Kacheln kopieren. (Bei einer anständigen Implementierung.)

Nun so weit reichen eine Kenntnisse nicht! Ich kenne den Sourcecode von Java nicht ;)

Wie Du merkst gibt es unterschiedliche Herangehensweisen an die Dinge, mit unterschiedlichen Vor- und Nachteilen und man kann Dinge anders lösen als in Objective-C!
Hier haben wir definitiv einen Nachteil, wenn man Strings so verwendet wie man es aus anderen Sprachen kennt. Da aber ein Großteil der Stringnutzung ein stumpfes Ausgeben von impliziten Konstanten (Literalen) darstellt und für Stringmanipulationen ein Extraobjekt ( der Stringbuffer) bereitsteht ist das überhaupt kein Problem. Es gilt halt wie immer: "know your tools" und "nur weil etwas anders ist muß es nicht schlechter sein!".
 
Schlecht implementiert, das darf nicht passieren. Beide Varianten müssen einen String erzeugen, beide "verschmelzen". append muss dazu die einzelnen Bytes kopieren, da es veränderlich ist und sich mit dem Werteobjekt keinen Speicher teilen darf. Das neue Objekt muss einfach zwei Zeiger in Kacheln kopieren. (Bei einer anständigen Implementierung.)
Du meinst, dass bei der ersten Variante dann ein Stringobjekt entstehen sollte, der 1 Mio Zeiger auf (Teil-)Stringsobjekte enthält?
 
Du meinst, dass bei der ersten Variante dann ein Stringobjekt entstehen sollte, der 1 Mio Zeiger auf (Teil-)Stringsobjekte enthält?

Wie groß sind denn deine Teilstrings? 10 Zeichen, 20 Zeichen, 100 Zeichen?

Du darfst dir dann ja selbst ausrechnen, wie groß der String ist …

Vor allem möchte ich mal deiner HD zuschauen, wenn Sie am Anfang des Strings 10 Zeichen einfügt. Dann werden mal eben 20 Millionen Zeichen von der Platte gelesen und wieder herausgeswappt. Nur um sie ein paar Bytes nach hintern zu verschieben.

Das hältst du wirklich für besser?

Ich denke mal, dass jede String-Implementierung mit Kacheln arbeitet. Natürlich werden die auff Vorrat angelegt, also eine gewisse Mindestgröße haben.
 
Zuletzt bearbeitet:
Nun so weit reichen eine Kenntnisse nicht! Ich kenne den Sourcecode von Java nicht ;)

Wie Du merkst gibt es unterschiedliche Herangehensweisen an die Dinge, mit unterschiedlichen Vor- und Nachteilen und man kann Dinge anders lösen als in Objective-C!
Hier haben wir definitiv einen Nachteil, wenn man Strings so verwendet wie man es aus anderen Sprachen kennt. Da aber ein Großteil der Stringnutzung ein stumpfes Ausgeben von impliziten Konstanten (Literalen) darstellt und für Stringmanipulationen ein Extraobjekt ( der Stringbuffer) bereitsteht ist das überhaupt kein Problem. Es gilt halt wie immer: "know your tools" und "nur weil etwas anders ist muß es nicht schlechter sein!".
Die Implementierung und ihr Laufzeitverhalten haben wir ja für einen Fall gesehen. Nein, ich kenne die Java-Implementierung nicht, sehe aber das Laufzeitverhalten.

Die Implementierungsidee ist auch unabhängig von irgendeiner Programmiersprache, genauer: irgendeinem Framework.

Insofern habe ich keinen Vergleich angestellt, schon gar nicht zwischen Java und Objective-C. Ich habe das nicht einmal für Objective-C nachgeprüft. Daher ja auch Forschungsprojekt. Mir geht es alleine um den Grundgedanken der immutable Container, der in zahlreichen Frameworks umgesetzt ist und dabei auch in Java und Objective-C/Cocoa.
 
Zurück
Oben Unten