Best Practice Auslagerung von Code = Performance Optimierung?

LeNkUeP

Mitglied
Hallo zusammen,

ich habe eine sehr allgemeine Frage zu dem Thema Auslagerung von Code.
Die grundsätzliche Frage ist ob die simple Auslagerung von Codeteilen die Performance verbessert.

Der Code unserer Firma ist extrem groß und hat immer wieder die gleichen redundanten Codeblöcke (Ergebnis einer RPG-Java Migration). Nach einer sehr groben Schätzung kann ich von einem Wert jenseits von 1.5 Millionen Codezeilen ausgehen. Dabei haben manche dieser Codeblöcke eine Länge von 100 Zeilen. Manche aber auch nur 15. Die Codeblöcke arbeiten immer nach dem Prinzip: 1. Initialisierungen/Setzungen von Variablen, 2. Aufrufen von Prüfprogrammen, 3. Fehlerbehandlungen etc.
Meiner Bachelorarbeit behandelt die automatische Auslagerung dieser Codekonstrukte. Bisher kann ich ca. von 1/2 an Mindesteinsparung von Code ausgehen. So wird immerhin aus 1,5 Millionen "nur noch" 750.000.

Klar bietet das Speichervorteile doch meine Frage ist ob es auch Optimierungen bezüglich der Wartezeiten/Performance gibt/geben kann.
Ich erzeuge pro Typ dieser Codeblöcke ein Objekt. Auf diesem werden dann parametrierte Methoden aufgerufen die im Grunde das Gleiche ausführen, halt nur ausgelagert sind und so nur einmal programmiert werden müssen. Generell würde ich sagen dass es jetzt so (nicht spürbar) etwas langsamer laufen muss (wegen zusätzlicher Objektinitialisierung und Kommunikation nach außen). Doch ist es vielleicht gerade bei dieser enormen Menge auch möglich einen Performance Gewinn daraus zu ziehen?

Die Klassen und Programme welcher diese Codeblöcke verwenden sind auch um die 50.000 Zeilen groß jeweils (wenn nicht sogar noch viel größer).

Ich hoffe ich habe meine Frage gut erklärt🙂
Danke für alle Antworten und Ideen.

Gruß
Lennart
 
Es ist von Vorteil, kleine Methoden zu haben. Es gibt in der HotSpot JVM diverse Thresholds/Limits für das Kompilieren/Optimieren von Bytecode in nativen Code und, ob weitere Optimierungsschritte wie etwa Inlining und darauf aufbauend Espace Analysis und Scalar Replacement Anwendung finden können.
Im Vorhinein zu sagen, ob eine Optimierung etwas bringt, ist sehr schwer zu sagen. Es hängt davon ab, ob der optimierte Code "kalt", "warm" oder "heiss" ist (wie häufig wird er aufgerufen?). Dementsprechend gibt es dann auch unterschiedliche Thresholds, ob und wie der Code von der JVM bzw. dem JIT optimiert wird.
Wenn du z.B. eine Methode mit einem if-Statement hast, in dem der then-Fall wenig Code beinhaltet, aber sehr sehr häufig aufgerufen wird, und der else-Fall viel Code beinhaltet, aber sehr sehr selten bis gar nicht aufgerufen wird, dann lohnt sich auf jeden Fall eine Auslagerung des else-Falls in eine eigene Methode, damit die Methode, die das if-Statement beinhaltet, eine Chance hat, JIT-Kompiliert zu werden, wenn sie sonst zu gross wäre und der JIT sagen würde: "Neee, diese Methode probiere ich erst gar nicht zu kompilieren, sondern interpretiere sie nur".
Informiere dich also einfach mal über die diversen Thresholds und Optimierungen der von dir eingesetzten JVM.
Ich empfehle auch wärmstens, den Code mit einem guten Sampling Profiler zu profilen und auch, dir mit Hilfe von jitwatch anzuschauen, welche Optimierungen der JIT auf die einzelnen Methoden anwendet, und wenn eine Optimierung nicht angewendet wird, warum nicht.
 
Also das Reine Entfernen von Duplikaten hat sicher Performance-Technisch keine Vorteile. Im Gegenteil: Rein technisch gesehen brauchst dann ja immer einen Methodenaufruf wo jetzt der Code direkt steht (Auch wenn das Zeittechnisch sicherlich zu vernachlässigen sein dürfte).
Der große Vorteil ist aber eben die Wartbarkeit. Wenn sich an der Initialisierung mal was ändert, dann must du es im Moment an 1000 Stellen im Code ändern. Danach nur noch an einer. Aber eben genau das kann natürlich auch gefährlich werden. Wenn du nämlich nur für einen Spezialfall eine etwas andere Initialisierung haben willst, dann fängt es wieder an: Mache ich doch eine zweite Methode dafür oder gebe ich der ersten einen weiteren Parameter? Wie viele Parameter können das dann irgendwann werden? Blickt das dann noch jemand?

Also generalisieren kann man es einfach nicht. Es kommt immer auf den expliziten Anwendungsfall an wie man sich entscheidet.

Gruß

Claus
 
Also das Reine Entfernen von Duplikaten hat sicher Performance-Technisch keine Vorteile. Im Gegenteil: Rein technisch gesehen brauchst dann ja immer einen Methodenaufruf wo jetzt der Code direkt steht (Auch wenn das Zeittechnisch sicherlich zu vernachlässigen sein dürfte).
Ganz pauschal kann man das so auch nicht sagen, aufgrund der erwähnten Grenzen des JITs, was die Grösse von zu optimierendem Bytecode einer Methode angeht, bzw. der Länge des IR (Intermediate Representation) ASTs der Methode. Eine sehr grosse Methode einfach in mehrere kleinere zu zerpflücken, kann durchaus einen sehr grossen Performancegewinn ausmachen, wenn das Zerpfücken dazu geführt hat, dass die Methoden für sich gesehen klein genug sind, um ge-JIT-ted zu werden. Und Methodenaufrufe an sich gibt es in einer JVM sowieso nur noch relativ selten im aus dem Bytecode kompilierten nativen Code, da sehr sehr viel bereits optimistisch mit type-guards ge-inline-d wird (wenn es die Methodengrösse und die Aufruftiefe zulässt), wenn es sich um monomorphe oder bimorphe Aufrufe handelt, oder ohne Guards, wenn es sich um private oder statische Methodenaufrufe handelt.

Bei deiner Argumentation bezüglich Wartbarkeit bin ich allerdings absolut deiner Meinung!
 

Zurück
Oben