new - wie macht das die VM?
-
Optimizer schrieb:
Hoi,
... dass die VM für jedes Objekt vom Betriebssystem Speicher anfordert.
...Warum sollte sie nicht?
-
Ingo aka Desert Hawk schrieb:
Optimizer schrieb:
Hoi,
... dass die VM für jedes Objekt vom Betriebssystem Speicher anfordert.
...Warum sollte sie nicht?
Weil das für kleine Objekte höllisch ineffizient ist. Deshalb macht das auch niemand.
-
10.000mal
{
- Erstellen eines Arrays von 1.000 Zeigern auf ein MyClass-Objekt
- Erstellen von 1.000 MyClass-Objekten mit new (Aufruf Standardkonstruktor!) und Zuweisung der Zeiger an diese Objekte
- Löschen aller 1.000 Class-Objekte
}C++ (Release-Build, VC++ .Net 2003): 3746ms
Java (sichere Arrays, bei jedem Indexzugriff Überprüfung!): 2404msIch hoffe mal, ich hab das einigermaßen equivalent für beide Sprachen geschrieben :
void main() { DWORD start = GetTickCount(); for (int counter = 0; counter < 10000; ++counter) { static const int length = 1000; // a ist ein Array von 1000 Zeigern auf ein MyClass-Objekt. MyClass *a[length]; // Jedem Zeiger a[i] wird ein neues MyClass-Objekt zugewiesen. for (int i = 0; i < length; ++i) a[i] = new MyClass(); // Hier werden alle MyClass-Objekte wieder gelöscht. for (int i = 0; i < length; ++i) { delete a[i]; a[i] = NULL; } } long time = GetTickCount() - start; cout << time << "\n\n"; }
public static void main(String[] args) { long start = System.currentTimeMillis(); for (int counter = 0; counter < 10000; ++counter) { // a ist ein Array von 1000 Zeigern auf ein MyClass-Objekt. MyClass[] a = new MyClass[1000]; // Jedem Zeiger a[i] wird ein neues MyClass-Objekt zugewiesen. for (int i = 0; i < a.length; ++i) a[i] = new MyClass(); // Hier werden alle MyClass-Objekte wieder // oder was auch immer der Garbage Collector // macht. :) ; } long time = System.currentTimeMillis() - start; System.out.println(time); }
Und so schaut die Klasse aus:
class MyClass { public MyClass() { x = 1; y = 2; z = 3; bla = 5; blub = 10; hurr = 15; a = 78643.723; b = 987690.2765; c = 786.9623978; } public int x, y, z; public long bla, blub, hurr; public double a, b, c; }
Hoffentlich ist da jetzt kein Fehler drin, ich hab das mal schnell zusammengehackt :
-
Und was willst du damit aussagen? Der GC vereinfacht einiges. Würdest du alles direkt vom OS holen, könntest du die Zeiten mindestens verzehnfachen.
-
Wo soll ich direkt vom OS holen? Bei C++ mach ich das. Und bei Java scheint es mir schneller zu sein, es von der VM zu holen als 1.000*10.000mal das Betriebssystem zu fragen (obwohl ich jetzt auch nicht weiss, ob das der Compiler in C++ noch optimiert hat).
btw, mir fällt grad noch auf, dass die Klasse in Java größer ist, weil ein long in C++ nicht 64 Bit unter Windows hat.
-
Bei C++ mach ich das.
Und woher kannst du dir so sicher sein, das bei C++ kein Speicherpool genutzt wird?
-
Weil es sonst wahrscheinlich mindestens genauso schnell wäre? Bei C++ muss man das halt anscheinend von Hand machen.
-
Optimizer schrieb:
Wo soll ich direkt vom OS holen? Bei C++ mach ich das.
Vergiss es. Wenn es so wäre, könntest du die Zeiten mindestens verzehnfachen, wenn das reicht (sagte ich aber schon).
Der Grund ist schlicht und einfach, dass der Java-Heap aufgrund des Garbage Collectors wesentlich billiger zu verwalten ist. Neue Objekte werden anfangs erzeugt, indem ähnlich wie beim Stack ein Pointer erhöht wird. Objektzerstörung gibts nicht (ausser bei Klassen mit Finalizer).
-
Bashar schrieb:
Neue Objekte werden anfangs erzeugt, indem ähnlich wie beim Stack ein Pointer erhöht wird. Objektzerstörung gibts nicht (ausser bei Klassen mit Finalizer).
Das war in etwa meine Theorie (siehe oben).
Wie das jetzt im einzelnen in C++ gehandhabt wird, weiss ich nicht. Da werden die Compiler sicher auch einiges rausholen können, aber scheinbar nicht so viel wie in Java. Ich wollte das mal rausfinden, weil man in Java doch weitaus häufiger auf new zurückgreifen muss als in C++. Natürlich wird es wohl nie ganz so schnell sein, wie wenn man in C++ Objekte auf dem Stack anlegt.Ich bin grad so dabei, mir ein bisschen anzuschauen, wie es in Java mit der Performance ausschaut. Auch Arrays sind eigentlich nicht wesentlich langsamer. Ich habe mit BubbleSort 50000 Elemente sortiert (dabei gibt es ewigst viele Zugriffe, weil BubbleSort sehr ineffizient ist).
Ergebnis: Java ist 1,5fach langsamer - aber was ist das gegen die Sicherheit? In C++ manuell den Index zu prüfen, scheint mir viel langsamer zu sein als die Lösung in Java.
-
hmmm, mal ehrlich, mir fällt spontan kein Anwendungsfall ein, bei dem man 10.000 kleine Objekte braucht
-
Mir schon, habe letzte Punkte gemalt (Sternenscroller), und für jeden habe ich new Color() gemacht. Mit C++ hätte ich mir das nicht getraut.