Performance Objektallokation

D

DrMotha

Gast
Ich muss ungefähr 20 Mal in der Sekunde rund 6x250000 also ca. 1,5 Mio Objekte anlegen (einer Vector3-Klasse, die drei floats enthält). Derzeit ist der Vector3 immutable, dementsprechend auch die vielen Objekte.

Ist es besser mutable Objekte zu verwenden oder ist die Objektallokation nicht das Bottleneck sondern die Berechnungen? Wie kann ich am besten mit Hilfe des NetBeans-Profilers herausfinden ob die Objektallokation das Bottleneck meiner Applikation ist?

Die CPU-Zeit sit noch nicht auf 100% obwohl ich genügend Threads liefere damit es alle Cores ausnutzen könnte.

Es geht um einen Rasterizer, und hier besonders um die Performance des Pixel-Shaders. Also da wird pro Pixel (500x500 davon) eine gewisse Anzahl an Vector-Multiplikationen durchgeführt.

Hoffe ihr könnt mir da etwas unter die Arme greifen bzw. habt gute (und vor allem aktuelle) Artikel für mich.

Vielen Dank im voraus!

LG
Bernhard
 

DerEisteeTrinker

Bekanntes Mitglied
Grundsätzlich ist eine Objektallokation zeitintensiver als eine Wertzuweisung. Man müsste aber überprüfen, ob es sinnvoller ist, wenn du die Objekte vorhälst in einer Datenstruktur. Denn bei so vielen Objekten könnte ich mir vorstellen, dass das "Objekt suchen" auch einiges an Zeit beansprucht.

Miss einfach mal mit System.nanoTime() die Zeit. Das mehrfach hintereinander und dann veränder die Implementierung. Schau dir aber auch an, wie sich der Speicher verhält und ob die Verteilung noch ok ist für den Anwendungsfall. Veränder auch die HotSpot-Variante von Client auf Server oder andersherum. Bei Server brauch er etwas länger mit dem Start der Anwendung, weil er aggressiver von sich aus optimiert. Das kann dir unter Umständen noch einiges an Zeitersparnis bringen.
 

Marco13

Top Contributor
Bis vor kurzem hätte ich auch gesagt, dass die Objektallokation teuer sein kann. Sowas wie "Object pooling" wird grundsätzlich nicht empfohlen, die neuen JVMs optimieren da schon ganz gut. Aber neulich auf der JAX hat Brian Goetz in einem Vortrag angedeutet, dass Performance, die vermeintlich durch Allokationen verloren geht, auch durch Caching-Effekte verloren gehen kann. Ich vermute, dass das auch vom konkreten Anwendungsfall abhängt, aber ... man könnte pauschal sagen: "Er wird's wohl wissen"...

Das Problem bei solchen Dingen ist, dass da auch ein Profiler nur bedingt weiterhelfen kann. Solche Effekte sind schwer zu messen. Aber natürlich wäre ein Profilerlauf der erste Ausgangspunkt.

Die Empfehlung, die OO-Puristen jetzt vielleicht weh tut: Bei wirklichen Low-Level-High-Performance-Aufgaben ist und bleibt ein echter, roher float[3*n]-Array immer noch das schnellste. (Dass man den später leichter an die GPU schicken kann ist nur ein Teilaspekt, der jetzt vielleicht noch nicht relevant ist). Das heißt aber nicht, dass man den nicht "so schnell wie möglich" (d.h. möglichst direkt nach der "Schicht", die die low-level-Berechnungen macht) hinter irgendeinem Interface verstecken sollte.
 

Ergometh

Mitglied
Wie bereits genannt ist es ratsam, erst einmal festzustellen, ob die Objekterzeugung und Einsammlung durch den Garbage Collector das Problem ist.

Das Erzeugen derartig vieler Objekte pro Sekunde halte ich jedoch für sehr bedenklich. Immutables werden meist als eine Art Krücke verwendet weil Java leider keinerlei strukturierte Wertetypen anbietet.

Datenobjekte mit denen viel "gerechnet" wird würde ich niemals als immutable implementieren.

Java müllt stets den Speicher voll um dann bei der garbage collection herauszusuchen, welche Objekte nicht mehr referenziert werden. Je mehr noch referenzierte Objekte es allerdings gibt, umso langsamer dürfte auch das werden - bedingt durch den verwendeten Algorithmus.

Sehr große Felder von Datenobjekten lohnen ggf. auch der "Einbettung". Warum nicht einfach alle xyz-Werte von tausenden von Vektoren in einem Array ablegen. Dies ist natürlich eine reine Performanceoptimierung und erfordert mehr Programmieraufwand, beispielsweise um die xxz-Werte dann in die Vektoren zu kopieren.

Anhänger der "reinen" objektorientierten Lehre werden hoffentlich alle Haare grau. Aber ich denke es geht um problemlösende Anwendungsentwicklung.
 

Empire Phoenix

Top Contributor
Immutables können allerdings effizienter garbagecoolected werden unter umständen.

Zb. wenn die nur local existieren als zwischenergebniss sind neue garbagecollectoren durchaus in der lage die direkt zu entsorgen.
 

Empire Phoenix

Top Contributor
Ansonsten gibt es die JSTackAlloc bibliothek, die es ermöglicht object pools sehr kompfortabel einzubauen (im sinne von das die per bytecode manipulation sich um vieles kümmert und man nur andeuten muss das die objecte daraus sein sollen. Wird zb von der java implementierung der bullet physic engine benutzt, da diese enorme mengen an zwischenergebniss objecten hat.
 

Marco13

Top Contributor
@Ergometh: Da hat sich einiges gatan, die Leute die die GC's schreiben sind nicht blöd ;) Ich glaube unter dem Stichwort "Escape Analysis" wird ein Verfahren verstanden, bei dem der GC feststellen kann, ob ein Objekt gelöscht werden muss oder wieder verwendet werden kann, al GANZ einfacher Fall sowas wie
Code:
for (int i=0; i<100; i++)
{
    Vector3f v = new Vector3f(i,i,i);
    result.add(v);
}
aber eben auch in deutlich komplizierteren Zusammenhängen. Trotzdem habe ich auch die Tendenz eher zu sagen: Wenn man ihm Arbeit sparen kann, kann man das ja machen, sofern es keine "premature Optimization" ist.
 

Ergometh

Mitglied
Bzgl. Marco13:

Escape Analysis ist ein interessanter Hinweis und sicher eine Verbesserungsmöglichkeit des Compilers, Interpreters oder Just-In-Time-Compilers für die Performance der Garbage Collection. Letztlich verbessert man damit aber lediglich ein Problem das man sich selbst eingebrockt hat. Und das Erzeugen eines neuen Objektes kostet leider auch wieder einiges.

Ich halte automatisches Speichermanagement und Garbage Collection für absolut wünschenswert für die Anwendungsentwicklung. Die Verwendung von Immutables zum "herumrechnen" ist jedoch grundsätzlich ein Fehler. Wie generell das massenhafte Erzeugen temporärer kleiner "Datenobjekte".

Das Fehlen von (strukturierten) Wertetypen bzw. einer vergleichbaren Semantik von Call-By-Value und Wertezuweisung schafft in Java leider oftmals das Problem zusätzlichen Kodieraufwands mit entsprechenden zusätzlichen Fehlerquellen. C# bietet hier "struct" als Lösung. Dann kann man letztlich bezüglich Wertetypsemantik arbeiten wie in C/C++. Ohne Slicing-Risiko da ohne Vererbung. Aber das hilft dem Fragesteller alles nichts ...
 

slawaweis

Bekanntes Mitglied
Ist es besser mutable Objekte zu verwenden oder ist die Objektallokation nicht das Bottleneck sondern die Berechnungen? Wie kann ich am besten mit Hilfe des NetBeans-Profilers herausfinden ob die Objektallokation das Bottleneck meiner Applikation ist?
bei solchen Problemen ist es immer gut ein Framework zu haben, welches flexibel ist. Neben der immutable Klassen, sollte es auch äquivalente mutable Klassen, sowie eine reine Array-Lösung geben. So kann man verschiedene Ansätze miteinander vergleichen und abwiegen. Nur die immutable Variante zu messen gibt keine Aussage, ob eine andere Variante effektiver oder einfacher zu programmieren wäre.

Slawa
 

Kr0e

Gesperrter Benutzer
Ich bin da gleicher Meinung wie Marco13. Außerdem könnte es doch sein, dass die JVM sowieso immutable Objects cached. Sprich in der JVM sind die vlt. garnicht immutable und können bei einer neuen Erstellung aus dem Cache genommen werden. Nur auf Javaebene sind die dann immutable.. Ich denke, dass da unheimlich viel optimiert wird, sonst würde man das auch merken... Erstell mal 10 Millionen String mit einem sich immer veränderndem Inhalt... Ich glaub nicht, dass 10 Millionen String erstellt und gelöscht werden.. Dafür geht das meiner Ansicht nach viel zu fix bei Java.

ABER: Das ist grad reine Spekulation... :p

Gruß,

Chris
 

tfa

Top Contributor
Besonders kurzlebige Objekte sind aus GC-Sicht praktisch kostenlos, Stichwort Generational GC. Ich sehe keinen Grund, eine Sprache mit überflüssigen Features wie Wert-Objekten zu verunreinigen, nur um eventuell "premature optimization" betreiben zu können. Das schafft mehr Probleme als dass es löst.
 
S

Spacerat

Gast
Genau dieses Problem hatte ich auch schon mal und zwar im 3D Bereich mit Morphing, allerdings mit dem Unterschied, dass meine Vector3-Klasse (bzw. Point3-Klasse) nicht immutable war. Ob nun die Objektallozierung von mutables teurer als die von immutables ist, kann ich nicht sagen, aber zumindest hat es mir sehr geholfen, ein temporäres 3D-Objekt mit gleicher Anzahl Vertices (jene mutable Point3-Klasse) zu erstellen um die einzelnen Morph-Werte darin ständig zu aktualisieren. Das hatte den Vorteil, dass nicht ewig neue Objekte erstellt wurden und der GC damit weitgehend entlastet wurde. Die Performance steigerte sich je nach verwendeter Hardware (ATI 9600, ATI X1950 und NVidia 260GT) vom 10-Fachen bis ins geschätzt (FPS-Anzeige wurde bei der NVidia-Karte gesprengt ;)) 1000-Fache.

@Kr0e: Gerade im 3D-Bereich, vorzugsweise bei Matritzen, Vektoren, Points und ähnlichem (vorallem bei Strings :)) scheint Objekt-Caching sehr wenig Sinn zu machen. Es gibt leider viel zu viele Objektmöglichkeiten, so dass dann entweder sehr viel Cache-Speicher benötigt oder der Cache viel zu oft bereinigt werden müsste um Platz für andere Objekte zu schaffen. Ist vorstellbar, das beide Aspekte performancemässig unheimlich teuer werden würden.
 
Zuletzt bearbeitet von einem Moderator:

Kr0e

Gesperrter Benutzer
Ich habe nicht gesagt, dass man selber cached, sondern, dass ich vermute, dass die JVM intern cached bis zu einem gewissen Limit, nicht mehr und nicht weniger ;) Mach doch einfach einen Test und dann sag nochmal, dass die Objekterstellung das Problem ist...
Ich habe jedenfalls noch nie Probleme gehabt in dieser Richtung und bezweifele es daher stark!

Kleines Beispiel zu ByteBuffers: Ich dachte immer, dass es vlt Sinn macht, benutzte ByteBuffer-Objekte wiederzuverwenden... Im Endeffekt war es effektiver, immer ein neues objekt zu erstellen... DAs kann nur heißen, dass die Buffer intern wiederverwendet werden... Ich glaube einfach, der Javaprogrammierer muss sich umn sowas kaum Gedanken machen, da die Genies von Sun/Oracle alles tun, damit selbst der schlimmste Code gut läuft :D

Beziehen sich deine Erfahrungen vlt auf ältere JVMs ?
 
M

maki

Gast
Ich glaube einfach, der Javaprogrammierer muss sich umn sowas kaum Gedanken machen, da die Genies von Sun/Oracle alles tun, damit selbst der schlimmste Code gut läuft
Normalerweise läuft das genau so, der Java Programmierer schreibt simplen Code, optimiert wird von der VM.

Falls das nicht reicht, kann man immer noch profilen.

Hypotetische "was wäre wenn" Diskussionen können mitunter sehr unterhaltsam sein, aber wirklich optimieren kann man nur mit einem Profiler, nicht mit theoretischen Diskussionen.
 
S

Spacerat

Gast
Beziehen sich deine Erfahrungen vlt auf ältere JVMs ?
Auf die Versionen 1.5 und 1.6. Nehmen wir mal an, es sollen 1,5 Mio mal pro Sekunde Vector3 mir 3 Flieskommawerten erstellt werden, das wären 4,5 Mio floats bzw. 18 Mio Bytes pro Sekunde also eine Datenrate von rund 18MB/s. Glaube kaum, dass eine VM aus Optimierungsgründen Objekte Cached geschweige denn überhaupt Cachen kann, wenn in der nächsten Sekunde Die selbe Anzahl jedoch komplett unterschiedliche Werte an Bytes aufkommt. Der GC wird mit Sicherheit auch nicht einmal pro Sekunde gestartet. Die Datenrate ist dabei natürlich von im- bzw. mutable völlig unabhängig. Für mich klingt es deswegen nicht zuletzt nur wegen meiner damaligen Ergebnisse vollig einleuchtend, dass die VM eine derartige Datenflut selbst bei genialster Implementierung gar nicht schafft. Im übrigen ist's dabei auch egal, wo gecached wird.
@maki: So hypothetisch finde ich diese Diskussion gar nicht, zumal mir bereits meine Ergebnisse vorliegen.
 
Zuletzt bearbeitet von einem Moderator:

Ergometh

Mitglied
Bzgl tfa:

Kurzlebige Objekte im Freispeicher zu erzeugen kann in bestimmten Fällen wirklich erstaunlich performant sein. Inwiefern praktisch kostenlos, das würde ich gern wissen.

Wenn es grundsätzlich so unproblematisch mit kurzlebigen Objekten ist stellt sich mir auch die Frage warum es die Methode von ...awt.Component
Code:
 Dimension getSize( Dimension result );
als Alternative zu
Code:
 Dimension getSize();
gibt.

Inwiefern das Vorhandensein einer Eigenschaft, wie Wertetypen eine "Verunreinigung" darstellt muss jeder für sich entscheiden.

Meine Zielsetzungen sind Entwicklungs- und Laufzeiteffizienz. Wobei die Entwicklungseffizienz meist wichtiger ist. Leider ist auch der Programmieraufwand durch Fehlen von Wertetypen i.d.R. höher.

Java arbeitet leider ausschließlich mit impliziten Zeigern (im Java-Kontext Referenz genannt) auf Objekte. Das Hantieren mit Zeigern und Call-By-Reference sind fehleranfällig. Um diese Fehler zu vermeiden hat man dann die Immutables auf breiter Front in Java eingesetzt. Ich denke C# hat hier aus den Fehlern von Java gelernt.

Bzgl. "Object Caching":

Object Caching im Sinne des Vorhaltens von Objekten im Nutzzustand, die dann anhand von Schlüsseleigenschaften gefunden werden bringt hier sicher nichts.

Ganz anders sieht es mit Object Reuse aus. Dies kann bei massenhaften kleinen Objekten, die immer wieder neu erzeugt werden große Performancegewinne bringen. Hier werden Objekte eines Typs (einer Klasse) unabhängig von ihrem Zustand zur Wiedernutzung in einem Pool gespeichert.
 

Kr0e

Gesperrter Benutzer
Ganz anders sieht es mit Object Reuse aus. Dies kann bei massenhaften kleinen Objekten, die immer wieder neu erzeugt werden große Performancegewinne bringen. Hier werden Objekte eines Typs (einer Klasse) unabhängig von ihrem Zustand zur Wiedernutzung in einem Pool gespeichert.

Das meinte ich eigentlich auch so... Hab mich mit Caching ein bisschen doof ausgedrückt .. =(
 

slawaweis

Bekanntes Mitglied
ich habe einen kleinen Benchmark geschrieben, speziell für Vektoren, vecmath.jar aus Java3D wird dafür benötigt. Ich habe es auf einem Q6600, JDK 1.6.0_24 und -Xms256m -Xmx512m mehrmals ausgeführt. Die Ergebnisse jeweils für Client und Server:

Code:
Client Immutable   6750 ms
Client Mutable     5688 ms

Server Immutable   5609 ms
Server Mutable     5515 ms

es scheint, dass die mutable Variante meines Tests etwas schneller ist, weil sie nur zwei Vektoren neu anlegt und nicht drei.

Der Quelltext, als Argument kann "0" für den immutablen und "1" für mutablen Test übergeben werden.

Java:
package performance;

import java.util.*;

import javax.vecmath.*;

public class OATest
{
 public static void main(String [] args)
  {
  if(args.length == 0 || args[0].equals("0"))
    {
    immutableTest();
    }
  else
    {
    mutableTest();
    }
  }

 public static void immutableTest()
  {
  long start = System.currentTimeMillis();
  immutableTest(10000000);
  long stop = System.currentTimeMillis();

  System.out.println("Immutable: " + (stop-start) + " ms");
  }

 public static void mutableTest()
  {
  long start = System.currentTimeMillis();
  mutableTest(10000000);
  long stop = System.currentTimeMillis();

  System.out.println("Mutable: " + (stop-start) + " ms");
  }

 public static void immutableTest(int count)
  {
  Random r = new Random();
  Vector3d v1, v2, v3;
  Vector3d [] array = new Vector3d[count];

  for(int i = 0; i < count; i++)
     {
     v1 = new Vector3d(r.nextDouble(), r.nextDouble(), r.nextDouble());
     v2 = new Vector3d(r.nextDouble(), r.nextDouble(), r.nextDouble());

     v3 = new Vector3d();
     v3.add(v1, v2);

     array[i] = v3;
     }
  }

 public static void mutableTest(int count)
  {
  Random r = new Random();
  Vector3d v1, v2, v3;
  Vector3d [] array = new Vector3d[count];

  for(int i = 0; i < count; i++)
     {
     v1 = new Vector3d(r.nextDouble(), r.nextDouble(), r.nextDouble());
     v2 = new Vector3d(r.nextDouble(), r.nextDouble(), r.nextDouble());

     v2.add(v1);

     array[i] = v2;
     }
  }
}

Slawa
 

ice-breaker

Top Contributor
Also in "Java Concurrency in Practice" in "11.4.7 Just say no to object pooling" heisst es, dass
Code:
new object
in Java mitlerweile nur noch rund 10 Maschineninstruktionen benötigt und somit schneller als malloc in C ist.
Der Vorteil von immutable Objekten wird in "3.5.2 Immutable objects and initialization safety" beschrieben, durch die Garantie, dass der Zustand neu erzeugter immutable Objekte auch sofort anderen Objekten sichtbar ist - auch ohne Synchronisierung.
Dies bezieht sich auf "3.5 Safe Publication" mit Listing 3.14 [1] sowie auf "3.5.1 Improper publication: when good objects go bad" mit Listing 3.15 [1] welches zeigt, dass einfach ein Objekt zu erzeugen und dem Rest der Welt bekannt zu machen nicht ausreicht, dass dieses auf Grund des Java Memory Modells auch wirklich sichtbar ist.

Bei Immutable Objekten geht es also um Geschwindigkeit, aber nicht durch die Objekterzeugung gewonne, sondern durch fehlende Synchronisierung, die man sich sparen kann, wenn man das Objekt an ein anderes publiziert z.B. an einen Konstruktor einer Klasse übergibt.

[1] Java Concurrency in Practice
 

Ergometh

Mitglied
Bzgl. slawaweis:

Ohne den Performancetest nachvollzogen zu haben: Es ist mir grundsätzlich unverständlich warum der Garbage Collector zwischen Mutable und Immutable unterscheiden sollte. Zumal dies eine Eigenschaft ist, die der Compiler bzw. Interpreter erst einmal erkennen muss.

Es sollte immer gleich schnell sein.

Bzgl. ice-breaker:

Danke für die genauen Quellenhinweise.

Ohne in eine Analyse der Algorithmen einzusteigen ist das mit der Anzahl von Maschineninstruktionen natürlich schwer nachvollziehbar. Grundsätzlich sehe ich auch keinen Grund warum Java hier langsamer sein sollte als C, da die Allokation ja intern in der JVM abläuft.

Leider kommt mein eigener simpler Performancetest mit JDK 1.6.0_25 bei Massenwiedernutzung mit Pool statt Erzeugen mit new zu einem anderen Ergebnis:
ca. 0,52 Sekunden vs. ca 2,7 Sekunden mittels new. Natürlich kein synchronisierter Pool.
Hier wurden 20 mal 1.000.000 Vektoren aus zwei int-Werten erzeugt/freigegeben.

Einen Reuse-Pool würde aber auch ich nur in dem seltenen Fall einsetzen das ich gezwungen bin sehr große Mengen Objekte immer gleicher Typen zu erzeugen und immer wieder frei zu geben. In der Regel ist allein die Gefahr noch verwendete Objekte fälschlich freizugeben ein guter Grund auf einen Pool zu verzichten. Zuerst sollte man immer prüfen, ob das Erzeugen/Wegwerfen großer Zahlen von Objekten nicht vermeidbar ist.

Für Concurrency sind Immutables als Ersatz für Call-By-Value bzw. ein (atomares) Value-Assign zweifellos nützlich.
 

Marco13

Top Contributor
Als kleinen Einschub mal den Hinweis von Brian Goetz: Write Dumb Code.
Das gilt aber sicher nicht für alle Fälle (für 90%, vielleicht auch 95% oder 99%, aber manche beschätigen sich eben (besonders) gerne mit dem Rest - wie klein er auch sein mag ;) ).

@slawaweis: Hab's jetzt nicht getestet, postuliere aber mal, dass dieser Vergleich eine Aussagekraft von nahe 0 hat: Was macht "random.nextDouble"? (Ich meine: Wie aufwändig ist das?)
(Wenn du es nicht machst, mach ich es ;) aber: ) Vielleicht sollte man das bei Gelegenheit mal umbauen, so dass die Erzeugung der Eingabedaten nicht mitgemessen wird (und auch die Problemgröße geändert wird, und beide Verfahren mehrfach abwechslend ausgeführt werden)
 
Zuletzt bearbeitet:

slawaweis

Bekanntes Mitglied
am Anfang des Threads ging es um die Frage, was performanter im Bezug auf Vektoroperationen ist. Objektpooling spielt hier keine Rolle. Es geht eher um das:

v3 = v1 + v2 vs. v2 += v1

also um die Frage, sollte man bei jeder Vektoroperation ein neues Vektorobjekt erzeugen oder sollte einem Vektorobjekt in der Formel der Wert direkt zugewiesen werden. Ich habe versucht diesen Umstand in einem Benchmark abzubilden. Selbstverständlich darf mein Code verändert und angepasst werden, um bessere Bedienungen/Ergebnisse zu bekommen. Ich würde mich auch über andere Benchmarks und deren Ergebnisse in Bezug auf Vektoroperationen freuen.

@Ergometh
den Garbage Collector habe ich bisher gar nicht erwähnt.

@Marco13
random.nextDouble() wird in gleicher Anzahl in beiden Varianten verwendet und stellt irgendeine Funktionalität in einem produktiven System dar. Ich habe es zuerst mit 0.0-len versucht, aber der Benchmark war zu schnell. In einem produktiven System werden ja auch unterschiedliche Werte verwendet, was ich mit random.nextDouble() abzubilden versuchte.

Am Anfang habe ich tatsächlich beide Varianten in einem Durchlauf abwechselnd ausgeführt. Doch in einem guten System würde man keinen Mischmasch von immutable und mutable für die selbe Sache verwenden, deshalb habe ich es getrennt. So sind auch bessere Aussagen über ein rein immutables und ein rein mutables System möglich.

Slawa
 
Zuletzt bearbeitet:

ice-breaker

Top Contributor
Leider kommt mein eigener simpler Performancetest mit JDK 1.6.0_25 bei Massenwiedernutzung mit Pool statt Erzeugen mit new zu einem anderen Ergebnis:
ca. 0,52 Sekunden vs. ca 2,7 Sekunden mittels new. Natürlich kein synchronisierter Pool.
Hier wurden 20 mal 1.000.000 Vektoren aus zwei int-Werten erzeugt/freigegeben.

neija es geht in meinen Quellen auch nur um die Erzeugung, du betrachtest damit ja die ganze Anwendung, wenn also dein JVM wenig Speicher zugewiesen bekommen hat, muss der Garbage Collector natürlich bei einem immutable-Ansatz viel öfter laufen als bei einem mutable-Ansatz, es sind dann zwar die GC-Durchläufe effizienter (Young-Generation durchsuchen) aber auch viel öfter.

Also Fazit wie immer: Aus Mikrobenchmarks kann man keinen Schluss ziehen.
 

Empire Phoenix

Top Contributor
Im übrigen was evtl eine sauber Lösung für den OP ersteller ermöglicht:
erstelle für alle Vektorfunktionen eine version bei der man das Ergebnisobject mitgeben kann und dort dann die werte eingetragen werden. Damit ist es einerseits noch möglich gut nachzuvollziehen wie die objecte wie manipuliert werden, und andererseits kann man sehr oft eine menge Allokationen sparen, wenn man sub weiß das man gerade die Position eines objectes ändern will kann man dann direct den Vector manipulieren.
 
S

Spacerat

Gast
@Ergometh: ...und wieder was gelernt. Object Reuse ist wohl der Fachbegriff, der mir fehlte. ;) Ich nannte es damals Object-Recycling. Zumindest weis ich jetzt ein wenig mehr wovon ich rede.
Das meinte ich eigentlich auch so... Hab mich mit Caching ein bisschen doof ausgedrückt .. =(
Warum sagst' des net gleich? "ein bisschen doof ausgedrückt" ist gut. "Verdrückt ausgekehrt" triffts besser. looool
Da wir jetzt genau wissen was du meinst bzw. was wir meinen, stellt sich mir die Frage, ob eine JVM neben Caching auch Object-Reuse von sich aus nutzt und ob sie selbstständig unterscheiden kann, wann sie was einsetzt. Wenn sie es kann, sind die Entwickler der JVM ausgesprochen genial. Aber ich gehe nach wie vor davon aus, dass sie es nicht kann, andernfalls müsste man sich ja keine Gedanken mehr darum machen ob man z.B. StringBuffer oder StringBuilder verwendet, bevor man irgendwelche Strings zusammen setzt.
Zumindest kann man schon mal davon ausgehen, dass bei massiver Objektflut Object-Reuse einem ständigem "new" vorzuziehen ist. Leider funktioniert Object-Reuse nur bei mutables. Deswegen mal 'ne klare Antwort für den Themenstarter. Ja, scheinbar ist es besser mutables zu verwenden.
 

Kr0e

Gesperrter Benutzer
Vlt. mal ganz lustig:

Beim Durchstöbern von JComponent fand ich das:

Java:
    private static void recycleRectangle(Rectangle rect) {
        synchronized(tempRectangles) {
            tempRectangles.add(rect);
        }
    }

Ziemlich interessant wenn man unser thema damit vergleicht... tempRectangles ist eine List von 11 elementen... diese Datei stammt noch aus älteren JVM Zeiten... Bei neueren Klassen habe ich sowas bisher nicht gesehen... Ich vermute, dass die JVM heutzutage sehr viel optimiert was solche Codezeilen überflüssig macht.. gut so!
 

Marco13

Top Contributor
Aus gegebenem Anlass nochmal ein Versuch - ja, Microbenchmarks, ich weiß, und Biased ist der auch ... aber ganz konkret: Wenn man einen Array mit vielen Punkten hat, und die mit einer Matrix transformieren will, und vor der Wahl steht, die Eingabepunkte direkt zu transformieren oder transformierte Kopien zu erstellen, wird der Unterschied schon recht deutlich:
Java:
package _main;

import java.util.Random;

import javax.vecmath.Matrix4f;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3d;

public class VecmathPerformance
{
    public static void main(String[] args)
    {
        Matrix4f matrix = new Matrix4f();
        matrix.rotX(45);
        
        for (int n=100000; n<=10000000; n+=100000)
        {
            Point3f v0[] = createInput(n);
            Point3f v1[] = createInput(n);
            
            long before = 0;
            long after = 0;
            
            before = System.nanoTime();
            immutableTest(matrix, v0, v1);
            after = System.nanoTime();
            System.out.println("immutable time for "+n+" elements was "+(after-before)/1e9+" result "+v0[0]);
            
            before = System.nanoTime();
            mutableTest(matrix, v0);
            after = System.nanoTime();
            System.out.println("  mutable time for "+n+" elements was "+(after-before)/1e9+" result "+v0[0]);
        }
    }
    
    private static Point3f[] createInput(int count)
    {
        Random r = new Random(0);
        Point3f array[] = new Point3f[count];
        for(int i = 0; i < count; i++)
        {
            array[i] = new Point3f(r.nextFloat(), r.nextFloat(), r.nextFloat());;
        }
        return array;
    }
    
    public static void immutableTest(Matrix4f matrix, Point3f v0[], Point3f v1[])
    {
        for(int i = 0; i < v0.length; i++)
        {
            Point3f v = new Point3f();
            matrix.transform(v0[i], v);
            v1[i] = v;
        }
    }
    public static void mutableTest(Matrix4f matrix, Point3f v0[])
    {
        for(int i = 0; i < v0.length; i++)
        {
            matrix.transform(v0[i]);
        }
    }
}

Um das nochmal zu betonen: In den ALLERmeisten Anwendungsfällen sind Objektallokationen das kleinste Übel (solche Sachen wie ein unbedarft aufgerufenes [c]logger.log(DEBUG, complexThing.toString());[/c] oder irgendwelches XML-rumgeserialisiere sind da viel kritischer), aber speziell bei Grafik (und dafür wird die Vecmath eben meistens verwendet) macht es offenbar doch (noch) einen deutlichen Unterschied. Und der Anwendungsfall (einen Array von Punkten mit einer Matrix transformieren) ist IMHO schon omnipräsent...
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
8u3631984 Frage Performance bei Linked List und Array List Allgemeine Java-Themen 5
H Performance einer Monte-Carlo-Simulation verbessern Allgemeine Java-Themen 6
goldmensch Datentypen Welche Methode hat die bessere Performance? Allgemeine Java-Themen 12
H Watson-Crick-Complement Performance Allgemeine Java-Themen 18
L Best Practice Auslagerung von Code = Performance Optimierung? Allgemeine Java-Themen 4
B Performance Messungen Allgemeine Java-Themen 4
J Threads verbessern die Performance NICHT ? Allgemeine Java-Themen 8
X Performance für Tomcat / Apache optimieren Allgemeine Java-Themen 2
I Performance - JDBC UPC PoolDataSoure Allgemeine Java-Themen 0
E Lambda filter performance Allgemeine Java-Themen 2
D Performance-Probleme mit Joda-Time Allgemeine Java-Themen 3
A Jasper Report Performance bei PDF erzeugen Allgemeine Java-Themen 0
A Best Practice Variablen vertauschen - Performance Allgemeine Java-Themen 1
R DBUnit Performance Probleme Allgemeine Java-Themen 0
P Performance: super explizit erwähnen oder weglassen? Allgemeine Java-Themen 5
S starke performance probleme des forums Allgemeine Java-Themen 10
C Performance Tips Allgemeine Java-Themen 13
A Performance/Speicherplatz-Nutzung bei Tests Allgemeine Java-Themen 6
R Java Performance testen Allgemeine Java-Themen 18
StrikeTom Java Performance Fragen Allgemeine Java-Themen 5
V Performance steigern Allgemeine Java-Themen 7
D Reflection-Performance Allgemeine Java-Themen 7
M Einfluss von Caching auf die Performance (große Arrays) Allgemeine Java-Themen 24
R Collections Performance einer HashMap Allgemeine Java-Themen 26
i<3java [Groovy/Grails](oder auch java) Mögliche Performance Probleme bei Mailversendung Allgemeine Java-Themen 2
J Java Performance nicht nachvollziehbar Allgemeine Java-Themen 3
I Library für High Performance Mime Type Erkennung Allgemeine Java-Themen 8
S Performance Frage: Objekt oder static? Allgemeine Java-Themen 33
M Runtime.exec() - Performance / Frage zu Threads Allgemeine Java-Themen 5
M Performance Allgemeine Java-Themen 6
M Performance Allgemeine Java-Themen 5
E Performance website download Allgemeine Java-Themen 13
MQue Performance Methodenaufruf - if Abfrage Allgemeine Java-Themen 19
hdi Was frisst in meinem Programm den Speicher / verschlechtert die Performance Allgemeine Java-Themen 11
J Performance von Java GUI-Anwendungen Allgemeine Java-Themen 2
U Java Performance im Vergleich zu C++ in speziellem Anwendungsfall Allgemeine Java-Themen 6
S Performance und Function Call Depth Allgemeine Java-Themen 6
H Performance Vorteil durch Wechsel der JVM? Allgemeine Java-Themen 6
A Performance: byte[] in byte[][][] konvertieren Allgemeine Java-Themen 2
T Performance ArrayList#remove Allgemeine Java-Themen 8
ARadauer Performance Pptimierung -Lesen/Schreiben Allgemeine Java-Themen 10
Chris81T Performance Problem durch mehrfaches Starten eines JAVA Prog Allgemeine Java-Themen 8
G Hibernate, JTable und Performance Allgemeine Java-Themen 17
M Listener und Performance Allgemeine Java-Themen 9
P Performance: Ziehen ohne Zurücklegen (große Datenmenge) Allgemeine Java-Themen 10
D Performance: ArrayList vs. Array vs. "Eigene Liste&quot Allgemeine Java-Themen 8
M nichtreferenzierte Objekte auf NULL setzen -> Performance Allgemeine Java-Themen 4
S Ursache für schlechte Performance Allgemeine Java-Themen 2
L Java Performance Check Tool Allgemeine Java-Themen 3
S Performance von Comparator Allgemeine Java-Themen 3
egrath Performance Problem mit File-I/O Allgemeine Java-Themen 6
S Performance Problem Allgemeine Java-Themen 11
X Java Performance auf Sun Systemen bzw. generell Allgemeine Java-Themen 4
T Performance String-Operationen und StringBuffer (1.4und 1.5) Allgemeine Java-Themen 18
P miese performance bei nem BufferedImage + repaint :( Allgemeine Java-Themen 6
T Performance-Grundlagen Allgemeine Java-Themen 4
G Performance Problem bei der Übertragung Server zum Client Allgemeine Java-Themen 3
V Performance Leck finden Allgemeine Java-Themen 3
T Tile Game Performance Allgemeine Java-Themen 32
M Performance enorm langsam Allgemeine Java-Themen 26
F Performance von Reflection vs Statisches Coden Allgemeine Java-Themen 4
M Performance: Java zu C/C++ bei Datenbankanwendung Allgemeine Java-Themen 3
Y unnecessary cast & Performance Allgemeine Java-Themen 29
conan2 Performance von paint() Allgemeine Java-Themen 2
G Performance JDOM - DOM - eigene HashMap (SAX) Allgemeine Java-Themen 2
F Bilder als "Thumbnails" laden - Performance Allgemeine Java-Themen 6
S Java3D Performance optimieren Allgemeine Java-Themen 5
F Wenn ihr Performance wollt nehmt C++ Allgemeine Java-Themen 39
N Performance-Test (Geschwindigkeit von Methoden vergleichen)? Allgemeine Java-Themen 4
S Performance Test mit JMeter Allgemeine Java-Themen 2
T Performance Allgemeine Java-Themen 8
J Anfängerliste für gute Performance? Allgemeine Java-Themen 3
Luma Performance-Problem mit RandomAcces File Allgemeine Java-Themen 4
I Performance bei "String <-> Byte"-Umwandlung Allgemeine Java-Themen 4
I Performance-Probleme bei Schleife Allgemeine Java-Themen 3
C Performance von FOR Schleifen Allgemeine Java-Themen 25
C Performance Vergleich, Java vs. Tcl/Tk Allgemeine Java-Themen 3

Ähnliche Java Themen

Neue Themen


Oben