2016-04-21 13 views
2

Ich habe Probleme, den richtigen Ansatz der Singleton-Klassen die leistungsstärkste Art zu finden. Ich habe 3 Ansätze, vielleicht kann mir jemand erklären, die effizienteste Art und Weise:Java: getInstance() Singleton Leistung

1:

public functionA() { 
    SingletonClassA.getInstance().callA(); 
    SingletonClassA.getInstance().callB(); 
    SingletonClassA.getInstance().callC(); 
    SingletonClassA.getInstance().callD(); 
    SingletonClassA.getInstance().callE(); 
} 

2.

public functionA() { 
    SingletonClassA tmp = SingletonClassA.getInstance(); 
    tmp.callA(); 
    tmp.callB(); 
    tmp.callC(); 
    tmp.callD(); 
    tmp.callE(); 
} 

3.

SingletonClassA tmp = SingletonClassA.getInstance();  
public functionA() { 
    tmp.callA(); 
    tmp.callB(); 
    tmp.callC(); 
    tmp.callD(); 
    tmp.callE(); 
} 

Ich sehe Code in welcher Ansatz 1 verwendet wird, aber ich denke, der bessere Weg wäre 2 (oder 3, wenn andere Funktionen auch SingletonClassA verwenden).

Ich komme aus c-Entwicklung, aber ich weiß nicht viel über Java und es ist Referenzen. Ich möchte nur, dass es nicht viel Speicher verbraucht und schnell ausgeführt werden kann.

+1

Haben Sie jeden Ansatz für Ihren Anwendungsfall gemessen? Um ehrlich zu sein, wird diese Art von Mikrooptimierung wahrscheinlich keine beobachtbare Wirkung haben. – sisyphus

+0

Ich verstehe, warum jemand mit einem C-Hintergrund eine solche Frage stellt, aber Sie müssen sich nicht mit einer solchen Mikrooptimierung beschäftigen. Sie verwenden Java jetzt, der Code wird in beiden Richtungen langsam sein ... :) –

Antwort

2

Niemals denken (oder richtig formuliert: annehmen/glauben), wenn über Leistung gesprochen wird.

Stattdessen: lesen Sie über den Java-Just-in-Time-Compiler und was es tut. Und Überraschung: Meistens wird das JIT solche Ideen zur Mikrooptimierung wie Ihre ... in die Röhre drehen. Greifen Sie nur auf Leistungsprobleme zu, wenn Probleme auftreten. Und dann: lernen Sie, einen Java-Profiler zu verwenden, um zu messen, was vor sich geht.

Bedeutung: Fokus auf SOLID Design; schreibe lesbaren, wartbaren Code ... der normalerweise sowieso "guten" Code ergibt; und ist viel lohnender als Zeit in Java zu verbringen. Außerdem: Wenn Ihr Code wartbar ist, wird es viel einfacher sein, Änderungen vorzunehmen, um bestimmte Leistungsprobleme zu beheben.

(ja, man sollte vermeiden, dumme Fehler zu machen; aber der erste und größte Fehler ist, dass davon ausgeht, dass dies einen guten/schlechten Effekt auf die Leistung hat).

Randnotiz: Erwägen Sie nicht, Singleton-Klassen zu verwenden, sondern Klassen mit einer einzigen Instanz.

1

Verwenden Sie eine Aufzählung mit einer einzigen Instanz.

Wenn Sie sich für ein Singleton in einer gleichzeitigen Umgebung interessieren und eine einfache Initialisierung wünschen, wählen Sie Initialization-on-demand pattern.

0

Wenn Sie die performante Version schreiben wollen, ist der dritte Ansatz ziemlich nahe, aber Sie eine private endgültige statische Variable verwendet werden soll, unnötige zusätzliche Look-ups zu vermeiden:

private static final SingletonClassA singletonA = SingletonClassA.getInstance();  
public functionA() { 
    singletonA.callA(); 
    singletonA.callB(); 
    singletonA.callC(); 
    singletonA.callD(); 
    singletonA.callE(); 
} 

Ich gehe davon aus, dass die So wie Ihr Singleton erstellt wird, wird es sich später nicht ändern, also ist auch static eine gute Wahl. Statisch wird 4/8 Byte Speicher (32/64 Bit VM) pro Instanz der Klasse speichern, da die Variable nicht mehr zu potenziell vielen Instanzen der Klasse gehört, sondern nur einmal existiert.

final Hinweise für den Compiler, dass sich diese Variable nach der ersten Deklaration nicht ändert, so dass keine Prüfungen auf Änderungen erforderlich sind. Beachten Sie, dass dies nur ein Hinweis ist, der die Entscheidung für den Compiler erleichtert. In den meisten Fällen kann der Compiler dies selbst bestimmen. Es ist jedoch auch eine gute Methode, dem Leser Ihres Codes eine schreibgeschützte Variable anzudeuten, und genau das tut final.

private stellt sicher, dass die Variable nicht Teil des vererbbaren Klassenabschnitts ist. Daher können Prüfungen auf Klassenhierarchien übersprungen werden. Dies ist jedoch mehr ein Leistungsgewinn zur Kompilierungszeit, da die JVM immer genau bestimmen kann, welche Version aus der Klassenhierarchie verwendet werden muss.

Beachten Sie auch, dass Klassenvariablen immer einen eindeutigen Namen haben sollten, der ihren Zweck angibt. tmp ist weder klar noch beschreibt es den Zweck.

jedoch: Der Leistungsgewinn in der nicht optimierten Code wird ein paar Nanosekunden bestenfalls, und sollte diese Funktion ein Teil der so genannten ‚heißen‘ Funktionen (= es wird genannt häufig), wird es weit optimiert werden darüber hinaus, was Sie mit dem Standard-Java-Code sowieso tun können. Daher ist der Leistungsgewinn durch das Umschreiben des Codes in diesem speziellen Fall völlig vernachlässigbar.

Wenn Sie nicht einen bestimmten Grund zu der Annahme haben, dass Ihr Code die Leistung beeinträchtigt, ist es immer besser, Code zu schreiben, der leicht zu lesen und zu pflegen ist, als auf einer so geringen Ebene zu optimieren. Die JVM ist viel besser darin, das für Sie zu tun, weil sie viel mehr Details über die ausführende Maschine weiß. Optimierungen, die Sie auf einem Intel-Rechner vornehmen, könnten i.E. Der Code wird langsamer auf einem ARM-System ausgeführt.

Optimierungen sollten immer auf der architektonischen (globalen) Ebene beginnen, und nur wenn Sie gemessen und bewiesen haben, dass bestimmte Codeteile danach immer noch zu langsam sind, sollten Sie über solche Optimierungen auf Mikroebene nachdenken.