Profilierung von Java-Code: Engpässe in der Praxis finden

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Einleitung: Warum Java-Code profilieren?

\n\n

Java-Entwicklung bedeutet nicht nur, korrekten Code zu schreiben, sondern auch schnelle, skalierbare Anwendungen zu erstellen. Selbst ein perfekt entworfenes System kann aufgrund einer einzigen nicht optimalen Zeile langsamer werden. Wie findet man diesen „Flaschenhals“? Die Antwort: Profilierung.

\n\n

Profilierung ist der Prozess der Datenerfassung über die Arbeitsweise einer Anwendung: Ausführungszeit von Methoden, Speichernutzung, Threads und CPU-Auslastung. Ohne sie wird die Optimierung zum Ratespiel. In diesem Artikel werden wir praktische Beispiele für die Profilierung von Java-Code durchgehen, lernen, Ergebnisse zu interpretieren und Engpässe zu finden.

\n\n

Wir betrachten zwei beliebte Tools: VisualVM (kostenlos, im JDK integriert) und JProfiler (kommerziell, aber leistungsstark). Alle Beispiele werden mit echtem Code sein.

\n\n

Hauptteil: Praxis der Profilierung

\n\n

1. Einrichtung der Umgebung und Start des Profilers

\n\n

Stellen Sie zunächst sicher, dass Sie JDK (8 oder höher) installiert haben. VisualVM wird mit JDK 8 und 9 mitgeliefert, für neuere Versionen muss es separat von der offiziellen Website heruntergeladen werden.

\n\n

Schreiben wir einen einfachen „langsamen“ Code zum Testen. Erstellen Sie die Klasse SlowApp.java:

\n\n
import java.util.ArrayList;\nimport java.util.List;\nimport java.util.Random;\n\npublic class SlowApp {\n    public static void main(String[] args) throws InterruptedException {\n        List<String> data = new ArrayList<>();\n        Random random = new Random();\n\n        // Simulation eines langen Datenladens\n        for (int i = 0; i < 100_000; i++) {\n            data.add(generateString(random));\n        }\n\n        // Datenverarbeitung\n        long sum = 0;\n        for (String s : data) {\n            sum += processString(s);\n        }\n\n        System.out.println("Result: " + sum);\n        Thread.sleep(10000); // Um Zeit zum Verbinden mit dem Profiler zu haben\n    }\n\n    private static String generateString(Random random) {\n        StringBuilder sb = new StringBuilder(100);\n        for (int i = 0; i < 100; i++) {\n            sb.append((char) ('a' + random.nextInt(26)));\n        }\n        return sb.toString();\n    }\n\n    private static long processString(String s) {\n        long result = 0;\n        for (char c : s.toCharArray()) {\n            result += c;\n            // Künstliche Verzögerung\n            for (int j = 0; j < 100; j++) {\n                result += Math.sqrt(j);\n            }\n        }\n        return result;\n    }\n}
\n\n

Starten Sie die Anwendung:

\n
javac SlowApp.java\njava SlowApp
\n\n

Während das Programm läuft (es schläft für 10 Sekunden), öffnen Sie VisualVM. Suchen Sie im linken Bereich Ihren Prozess (SlowApp) und doppelklicken Sie darauf. Gehen Sie zum Tab Sampler oder Profiler – Sie sehen Statistiken zu CPU und Speicher.

\n\n

2. CPU-Analyse: Finden der schwersten Methode

\n\n

Klicken Sie in VisualVM im Bereich Sampler auf die Schaltfläche CPU. Nach einigen Sekunden erhalten Sie eine Tabelle mit Methoden, sortiert nach Ausführungszeit (Self Time).

\n\n

In unserem Beispiel werden Sie sehen, dass die Methode processString mehr als 80% der Zeit belegt. Darin befindet sich die verschachtelte Schleife Math.sqrt(j). Dies ist der Engpass.

\n\n

Wie interpretiert man das?

\n
    \n
  • Self Time – Zeit, die direkt für die Ausführung der Methode aufgewendet wurde (ohne Berücksichtigung von Aufrufen untergeordneter Methoden).
  • \n
  • Total Time – Gesamtzeit, einschließlich aller verschachtelten Aufrufe.
  • \n
  • Invocations – Anzahl der Aufrufe der Methode.
  • \n
\n\n

Beispielausgabe (vereinfacht):

\n
Method                          Self Time (ms)   Invocations\nSlowApp.processString           8500              100000\nSlowApp.generateString          1200              100000\njava.lang.Math.sqrt             6000                

Blogs

Buchempfehlungen