Sollten Sie die Erstellung vieler kleiner Objekte minimieren?

10

Wenn Sie etwas schreiben, das häufig viele (1000) kleine Objekte erzeugt, sollten Sie versuchen, es für die Leistung zu minimieren? Vor allem, wenn Sie nicht wissen, auf welchem ​​System es ausgeführt wird, von Low- bis High-End-Desktops oder sogar von Mobilgeräten. Für Handys habe ich gehört, dass das Erstellen vieler Objekte die Leistung ein wenig beeinträchtigt, obwohl ich nicht weiß, wie wahr das ist.

Ich habe ein Beispiel, das diese Idee gut zeigt. Angenommen, in einem Grafikprogramm gibt es eine Methode, die für alle Zeichnungen verwendet wird, die idealerweise aufgerufen werden drawPixel(Point). Es können Tausende von Punkten erstellt werden, und es kann häufig wiederholt werden, wie in einem Spiel, in dem es mehr als 60 Mal pro Sekunde aufgerufen werden kann. Alternativ drawPixel(int x, int y)könnte verwendet werden, um die Erstellung vieler Punktobjekte zu minimieren.

In einem objektorientierten Design würde ich die Verwendung von Point bevorzugen. Die Verwendung primitiver Typen kann jedoch die Leistung erhöhen. Der Leistungsgewinn kann in den meisten Fällen vernachlässigbar sein, aber ich bin mir nicht sicher, was mobile oder ältere Maschinen betrifft. Was ist der Leistungsgewinn, wenn Sie so etwas tun, und sollte dies berücksichtigt werden?

Stripies
quelle
Es fällt mir schwer, Referenzen zu finden, um dies zu sichern, aber im Allgemeinen machen Sie sich in Java 8 keine Sorgen. Machen Sie keine offensichtlich dummen Dinge, aber wenn Sie nicht absichtlich verschwenderisch sind, sollte das System einwandfrei funktionieren. Sun / Oracle hatten ungefähr 20 Jahre Zeit, um die GC- und Speicherverwaltung zu optimieren, und sie sind wirklich gut darin geworden.
@Snowman Ich habe gehört, dass neuere Versionen von Java die Speicherverwaltung verbessern, aber das Problem, das ich sehe, ist, dass es keine Garantie gibt, dass der Benutzer keine ältere Version verwendet. Das ist ein Teil dessen, was mein Anliegen geschaffen hat.
Stripies
1
Führen Sie zuerst eine Leistungsmessung durch. Wenn Sie Probleme haben, überlegen Sie, wie Sie diese optimieren können. Aber bitte opfern Sie die Wartbarkeit des Codes nicht zu früh, da Sie glauben, dass Sie Leistungsprobleme haben könnten.
Spotted
2
@Stripies Leistung kurzlebiger Java-Objekte, die bereits in beantwortet wurden Sollten wir die Objekterstellung in Java vermeiden? . Wenn Sie jedoch jemals Hunderte Millionen solcher Objekte pro Sekunde verarbeiten müssen, überdenken Sie dieses Problem erst zu diesem Zeitpunkt.
Rwong
1
Wenn Sie sich Sorgen über ältere Java-Versionen machen, überprüfen Sie dies bei der Installation. Eine JVM, die alt genug ist, um ein Problem mit der Speicherverwaltung zu verursachen, weist auch viele bekannte Sicherheitsprobleme auf. Daher ist es ein Gefallen, Benutzer zum Aktualisieren aufzufordern. System.getProperty("java.version")(oder "java.vm.version") ist ein Ausgangspunkt.
Jerry Coffin

Antworten:

17

In der Regel nicht , sollten Sie nicht vermeiden Objekte aus Angst vor Leistungsverlust zu schaffen. Dafür gibt es mehrere Gründe.

  1. Die Verwendung von Objekten ist eine Art Sinn für die Verwendung von Java. Sie präventiv zu vermeiden, ist ein Zeichen dafür, dass die Entscheidung für Java möglicherweise nicht die richtige war.
  2. Leistungsprobleme sind bekanntermaßen schwer vorherzusagen. Gehen Sie niemals davon aus, dass etwas ein Engpass ist. Immer messen. Beim Performance Engineering geht es fast immer darum, kleine Änderungen genau am richtigen Ort vorzunehmen. Sie können nicht den richtigen Ort vorhersagen, ohne mehr zu messen, als Sie die Wirkung eines Medikaments ohne Experiment vorhersagen können.
  3. Die Kosten für die Objekterstellung werden stark überschätzt. In einer modernen JVM kommt es im Wesentlichen darauf an, einen Zeiger zu erhöhen (und bei Garbage Collectors der Generation sind die Kosten für die Verwaltung ebenfalls trivial). Es gibt viele Texte im Internet, die Ihnen raten, Objekte zu meiden, Objektpooling zu verwenden usw. Dieser Ratschlag war in den neunziger Jahren manchmal richtig. heute ist es meistens veraltet. Es ist sehr unwahrscheinlich, dass Sie genug Leistung erzielen, um die zusätzlichen Entwicklungskosten und die Komplexität zu rechtfertigen, die durch das Vermeiden oder Verwalten von Objekten entstehen.

Es gibt jedoch Orte, an denen es zunächst keinen Sinn macht, etwas zu einem Objekt zu machen. Das Übergeben von zwei Koordinaten an eine Zeichenroutine kann ein solcher Fall sein: Das Koordinatenpaar hat keine unabhängige Existenz, es hat keine Identität, es wird nur einmal verwendet und dann sofort verworfen usw.

Wenn dies der Fall ist, gehen Sie sicher vor und übergeben Sie zwei intSekunden, anstatt sie in ein Objekt zu wickeln. Der Punkt von OOP ist nicht, dass alles ein Objekt sein muss. Der Punkt ist, dass Objekte die Entwicklung an Orten erleichtern, an denen sie die natürliche Lösung für ein Problem der Datendarstellung darstellen. Vermeiden Sie Objekte nicht dort, wo sie sinnvoll sind - stellen Sie sie nicht dort vor, wo sie keinen Sinn haben.

Kilian Foth
quelle
2

Wenn Sie über Auswirkungen auf die Leistung nachdenken, bevor Sie Code geschrieben haben, sollten Sie davon ausgehen, dass Sie nicht wissen, was Sie tun.

Es gibt einen sehr kleinen Platz für Objekte in Java im Vergleich zu Grundelementen. Je kleiner Ihre Objekte sind, desto höher ist der Prozentsatz des Overheads. Ich habe jedoch vor langer Zeit gelernt, dass Dinge, die n verdoppeln, nichts im Vergleich zu Dingen sind, die n mit n multiplizieren.

Also ja, während Sie ein System finanzieren könnten, das die Hälfte der Größe oder sogar ein Viertel hatte, fragen Sie sich bitte, warum es Sie wirklich interessiert. Komplizierte Lösungen für dieses Problem werden nicht gut aufgenommen. Insbesondere, weil das Eintauchen in einen solchen Code verwirrend sein wird. Verwirrte Programmierer schreiben schlechten Code. Sie schreiben n mal n Code, der n log n Code sein sollte. Und sie brauchen länger, um es zu tun.

Wenn Sie mir jetzt mit einem Trick Platz sparen können, der in eine schöne Schachtel passt, in die ich die meiste Zeit nicht hineinschauen muss, können wir reden. Wenn es eine Box ist, kann ich sie gegen eine andere austauschen, wenn diese Box besser funktioniert. Ich kann sogar dafür bezahlen.

candied_orange
quelle
2

Bei der von mir durchgeführten Leistungsoptimierung ( Beispiel ) ist es für die Speicherverwaltung sehr einfach, ein Hauptschuldiger zu sein. Es ist mir egal, wie verrückt sie den neuen Operator und den Garbage Collector optimiert haben. Die schnellste Berechnung ist keine Berechnung. Wenn ich also feststelle, dass der Speichermanager einen guten Prozentsatz der Zeit in Anspruch nimmt und ich es nicht vermeiden kann, Objekte zu erstellen , finde ich einen Weg, sie wiederzuverwenden, anstatt ständig neue zu erstellen.

Ich tue dies nur , wenn ich muss Objekte. Für Grafiken normalerweise nicht. IMHO, Grafiken sollten gezogen , nicht gebaut . Sicher könnte man sagen, dass ein Bild aus Punkten, Linien, die sie verbinden, Polygonen, Text usw. besteht. Das bedeutet nicht, dass Sie keine Alternative haben , Objekte daraus zu machen, bevor Sie sie zeichnen . Ich zeichne sie einfach.

Es gibt eine Malmethode. Ich überschreibe das, zeichne alles auf eine Bitmap und blockiere dann die Übertragung auf den Bildschirm. Es sieht augenblicklich aus. Für die Mauseingabe gibt es Methoden zum Überschreiben, Erkennen von Klicken, Ziehen usw.

OOP ist aus bestimmten Gründen eine gute Idee. Diese Gründe gelten nicht in allen Situationen.

Mike Dunlavey
quelle
Ich stimme zu, aber ich stimme auch allen anderen zu, dass das Testen der einzige Weg ist, um sicher zu sein. Stellen Sie sicher, dass Sie Spezifikationen haben, die dies auf einfache / offensichtliche Weise tun, bevor Sie es optimieren ... aber ich stimme zu, dass Neu immer noch ein Problem sein kann.
Bill K
2

Gehen Sie voran und verwenden Sie kleine Zuordnungen. Moderne Speichermanager, insbesondere der hochoptimierte Java-Objektmanager, sind äußerst effizient. Speichern Sie wichtige Leistungsoptimierungen für ein Arbeitsprogramm.

Es ist sehr wahrscheinlich, dass die Gesamtleistung angemessen ist. Wenn Sie feststellen, dass dies nicht der Fall ist , profilieren Sie und nur dann die Leistung des Codes. In einer langen Karriere in der Softwareentwicklung habe ich gelernt, dass die Engpässe fast nie dort sind, wo Sie sie erwarten.

Ich hatte einmal ein Teammitglied mehrere Tage damit verbracht, die Suche nach Objektmitgliedern 20x schneller zu machen. Erfolg! Die beste Gesamtbeschleunigung bei der tatsächlichen Verwendung wurde jedoch in Hundertstel Prozent gemessen. Die Änderung wurde sofort zurückgesetzt, da für die Beschleunigung größere Speicherzuweisungen pro Mitglied erforderlich waren.

Bill Ferguson
quelle
1

Es ist ganz einfach: Wenn Sie 1000 kleine Objekte benötigen, erstellen Sie 1000 kleine Objekte und sorgen sich nicht darum. Wenn Sie 100 kleine Objekte benötigen , ist das Erstellen von 1000 kleinen Objekten dumm - erstellen Sie die Objekte, die Sie benötigen, und nicht mehr.

Wenn Sie sich Sorgen um die Leistung machen (und wenn Sie sich auch keine Sorgen um die Leistung machen), sollten Sie alle Funktionen einmal an einer Stelle schreiben lassen , wodurch Ihr gesamter Code einfacher und verständlicher wird. Dann , wenn Sie ein Leistungsproblem haben, dann Messen zeigen können Sie , dass es ein Ort , an dem das Leistungsproblem geschieht, die Dinge einfacher macht, und nur einen Ort , wo Sie brauchen , um es zu ändern. Oder das Messen zeigt, dass dieser eine Ort keine Probleme verursacht, also sind Sie fertig.

gnasher729
quelle