Leistungsoptimierung für Java-Apps

Ich denke, dass es bei manchen Menschen sehr häufig vorkommt, aber in Wirklichkeit stößt es häufig auf Probleme, und wenn es um Java-Optimierung geht, gibt es viele infrastrukturorientierte Optimierungsmethoden, z. B. das Ändern von GC-Richtlinien, also in der Anwendung Ich werde hauptsächlich die TIPPS-ähnlichen Dinge beschreiben, die realisiert werden können (soweit ich mich erinnere ...).

Leistungsproblem Fall

Missbrauch der Verkettung von Zeichenfolgen

--Problem: OutOfMemoryError, Verlangsamung

** Einzelheiten ** Insbesondere ist die Beschreibung wie folgt. Ich sehe es oft.

Zeichenfolge Verkettete Zeichenfolge= "";
Verkettete Zeichenfolge= Verkettete Zeichenfolge +Zusätzliche Zeichenkette 1;
Verkettete Zeichenfolge= Verkettete Zeichenfolge +Zusätzliche Zeichenkette 2;
Verkettete Zeichenfolge= Verkettete Zeichenfolge +Zusätzliche Zeichenkette 3;
Verkettete Zeichenfolge= Verkettete Zeichenfolge +Zusätzliche Zeichenkette 4;
System.out.print(Verkettete Zeichenfolge);

(Zusätzliche Zeichenfolgen 1 bis 4 sind Variablen vom Typ Zeichenfolge. Erstens denke ich, dass Sie + = verwenden können, aber es gibt ziemlich viele Leute, die auf diese Weise schreiben.)

Einige Verknüpfungen sind in Ordnung, aber selbst bei 5 oder 6 Verknüpfungen können je nach Anzahl der Ausführungen Probleme auftreten.

Im obigen Fall wird für jede Verkettung eine Instanz der String-Klasse erstellt, was sich auf die Anzahl der GC-Vorkommen aufgrund der großen Anzahl kleiner generierter Java-Objekte auswirkt. (Erhöhte Anzahl von GC-Vorkommen ⇒ Leistungsverschlechterung) Wenn eine große Anzahl von Schleifenanweisungen generiert wird, kann die Anzahl der Instanzen den nativen Bereich von Java Heap verschlingen. (Ob dies geschieht, hängt von der JVM-Implementierung ab.)

Das Mittel ist wie folgt.

Zeichenfolge Verkettete Zeichenfolge= "";
StringBuilder sb = new StringBuilder();
sb.append(Verkettete Zeichenfolge)
  .append(Verkettete Zeichenfolge 1)
  .append(Verkettete Zeichenfolge 2)
  .append(Verkettete Zeichenfolge 3)
  .append(Verkettete Zeichenfolge 4);
System.out.print(sb.toString());

(Obwohl die Generierungskosten von StringBuilder steigen, ist es im Allgemeinen effektiver, die Generierungskosten von String zu senken.)

--Wenn die Anzahl der Joins unter einem bestimmten Wert im Voraus bekannt ist, kann das Festlegen des Anfangswertes von StringBuilder die Leistung verbessern.

Missbrauch schwerer APIs (hauptsächlich Datumstyp)

--Problemereignis: Geschwindigkeitsverschlechterung

** Einzelheiten ** Als Typ, der häufig in Geschäftsanwendungen verwendet wird, denke ich, dass neben der Zeichenfolge ein numerischer Wert oder ein Datum steht, aber das Problem tritt häufig beim Datum auf. Dies liegt daran, dass im Fall von Java die Generierungskosten hoch sind, da bei neuem Datum Zugriff auf das Betriebssystem besteht.

Da das Datumssystem jedoch häufig von der Dienstprogrammklasse verwaltet wird und das Datum häufig im Dienstprogramm generiert wird (neues Datum), wird eine große Anzahl von Datumselementen in einer Geschäftsanwendung mit einer großen Anzahl von Elementen automatisch viele Male wiederholt. Dies kann zu einem neuen Datum und einer schlechten Leistung führen.

Als persönliche Erfahrung gibt es zum Beispiel die folgenden Fälle.

Als Lösung gibt es in diesem Fall beispielsweise die folgenden Methoden

Verlangsamung der externen Kommunikation (hauptsächlich externe Systeme wie Hosts und DBs)

--Problem: Unzureichende Ressourcen des externen Kommunikationsziels, Geschwindigkeitsverschlechterung

** Einzelheiten ** Beim Abrufen von Benutzerinformationen oder Vertragsinformationen vom Host (Altsystem) kann die Hostseite möglicherweise nicht zurückkehren, wenn diese jedes Mal erfasst werden. In diesem Fall wird es beim Anmelden nur einmal erfasst und die Informationen bleiben im Speicher erhalten. Ich denke, dass dies in einem normalen System geschieht, aber manchmal, wenn nur eine bestimmte Verarbeitung weggelassen wird oder eine neue Kommunikation stattfindet, kann es zu einem Problem werden, wenn eine solche Überlegung weggelassen wird. .. ..

In ähnlicher Weise können für die DB-Kommunikation Dinge, die während der Anmeldung als unveränderlich angesehen werden, wie z. B. Stammdaten, zwischengespeichert werden. Es gibt zwei Muster für das Caching: Das eine besteht darin, es einfach in Sitzungsdaten zu speichern und für jeden Benutzer zu haben, und das andere darin, es in einer Singleton-Klasse zu halten und für alle Benutzer gemeinsam zu haben.

Diese haben den Kompromiss einer erhöhten Speichernutzung, sodass Sie die Größe des Caches separat berücksichtigen müssen. In der Vergangenheit wurde es häufig zu einem Engpass bei DB-Servern, aber in letzter Zeit wird die Leistung des DB-Servers immer besser, und ich denke, dass es viele Fälle gibt, in denen ein Cache-Mechanismus wie JPA im Voraus vorhanden ist.

Starke E / A-Belastung auf niedriger Ebene, z. B. Dateivorgänge

--Problem: OutOfMemoryError tritt auf, was beim Umgang mit großen Dateien usw. sehr langsam ist.

** Einzelheiten ** Es gibt Fälle wie Leistungsprobleme beim Umgang mit Dateien mit einem Datenvolumen von mehreren hundert M oder mehreren G oder mehr, hauptsächlich in Java-Batches, und Fälle, in denen OutOfMemoryError überhaupt nicht verwendet werden kann.

Die folgenden Fälle können als Gegenmaßnahmen angesehen werden.

Runtime runtime = Runtime.getRuntime();
runtime.exec("Katze A Datei B Datei>Verkettete Datei");

(Zusätzlich zu concachi können Sie den Befehl diff für den Dateivergleich, awk für das Ersetzen von Zeichenfolgen usw. verwenden.)

Das Problem bei dieser Methode ist, dass sie vom Betriebssystem abhängig ist, wodurch die Portabilität eingeschränkt wird. Ich möchte es auf die Mindestanzahl von Stellen anwenden, nicht von Anfang an auf alle Stellen. (Wenn die Testumgebung Windows ist, die Produktion UNIX usw. ist, müssen Befehle für jede Umgebung am entsprechenden Implementierungsspeicherort usw. zurückgegeben werden können.)

Unnötige Synchronisationsverarbeitung

--Problem: Leistungseinbußen beim Zugriff auf mehrere Benutzer aufgrund der Java-Synchronisationsverarbeitung

** Einzelheiten ** Es gibt eine Methode, die einen Synchronisationsprozess (Synchronisationsblock) enthält, um einzelne Tonnen in Dienstprogrammklassen usw. zu verarbeiten. Wenn Sie diese einfach kopieren und eine andere Methode erstellen, obwohl es sich um eine Methode handelt, für die keine Synchronisationsverarbeitung erforderlich ist Der Synchronisationsblock wird beschrieben. Oder es ist zu sicher, der Synchronisierungsblock ist zu breit und es ist sehr wahrscheinlich, dass Sperren auftreten. .. ..

Die Korrespondenz ist einfach wie folgt.

--Entfernen Sie unnötige Synchronisationsblöcke

** Wenn Sie den Synchronisationsblock jedoch zu stark eingrenzen, wird dies zu einem threadsicheren Problem. Sie müssen daher sehr vorsichtig sein. ** Wenn es kein Problem gibt, ist es auch eine gute Idee, nicht zu antworten, selbst wenn eine unnötige Beschreibung vorliegt. ..

Desynchronisation der Verarbeitung

--Problem: Die Verarbeitung ist sehr schwer, kann aber nicht von einer kleinen Hand erledigt werden. Es gibt jedoch keine Anforderungen an die synchrone Verarbeitung. --Lösung: Verschieben Sie den Verarbeitungszeitpunkt

** Einzelheiten ** Es wird eine Änderung auf der Architekturebene sein, daher möchte ich vermeiden, so weit zu gehen, aber in Wirklichkeit denke ich, dass es basierend auf den Ergebnissen der Leistungstests implementiert werden kann.

Multiplexing verarbeiten

--Problem: Die Verarbeitung ist sehr schwer, aber die Verarbeitung kann parallelisiert werden. Darüber hinaus gibt es einen Spielraum bei den Serverressourcen. --Lösung: Multiplexen des Prozesses

** Einzelheiten ** Ich gehe von einem Stapel aus, aber ich denke, es gibt einige Fälle, in denen er online in Kombination mit Desynchronisation implementiert wird. Für Anwendungen, bei denen von Multiplexing ausgegangen wird, suchen wir nur nach dem optimalen Multiplexgrad. Wenn wir jedoch Anwendungen unterstützen, bei denen kein Multiplexing angenommen wird, ist dies auch eine Änderung auf Architekturebene, sodass dies eine wesentliche Änderung darstellt. .. ..

Leistungsprobleme identifizieren

Sammeln von Informationen in Protokollen

Überprüfen Sie, welche Verarbeitung schwer ist, einschließlich der Anwendung selbst, des Zugriffsprotokolls des WEB-Servers und des Protokolls des externen Kommunikationsziels. Grundsätzlich denke ich, dass die Protokollbestätigung die höchste Priorität hat. (Dies ist der schwierigste Teil, da Sie sich nicht in der Produktion anmelden können, aber ...)

GC log h

Dies ist auch ein Protokoll, aber im Fall von Java ist eine Leistungsverschlechterung in GC der häufigste Fall, daher ist es etwas Besonderes. Ich denke, es hängt von der JVM ab, aber im Allgemeinen sind die GC-Frequenz, ihr Typ (mit oder ohne vollständige GC), die GC-Zeit usw. die zu überprüfenden Punkte.

Sammeln von Informationen auf Betriebssystemebene

Ich denke, dass für jedes Betriebssystem ein Leistungsmonitor vorbereitet ist. Überprüfen Sie daher die CPU, den Speicher, den Betriebssystemzugriff usw. Bei Java-Apps sollte es keinen Speicherengpass im Betriebssystem geben. Daher muss hauptsächlich festgestellt werden, ob es sich um einen CPU-Engpass handelt. Selbst wenn die CPU zu 100% ausgelastet ist, kann die CPU-Auslastung aufgrund des häufigen Auftretens von GC aufgrund von Speichermangel steigen. Dies allein sagt also nichts aus, aber ...

Informationserfassung auf JVM-Ebene

Wenn Sie einen Thread-Dump erhalten können, können Sie den internen Status von Java überprüfen, indem Sie einen Thread-Dump im Leistungsproblemstatus abrufen. Bei Problemen mit Zeichenfolgen wird der Großteil der Anzahl der Objekte in Heap von Zeichenfolgen belegt, und bei Problemen mit der synchronen Verarbeitung werden viele Methoden mit einer Synchronisierungsklausel in Thread-Informationen belegt. , Und so weiter. Abhängig von der JVM können außerdem detaillierte Informationen zu Java-Objektinformationen abgerufen werden.

Recommended Posts

Leistungsoptimierung für Java-Apps
Java-Leistung Kapitel 1 Einführung
Janken App in Java
Java Performance Kapitel 3 Java Performance Toolbox
45 Techniken zur Optimierung der Java-Leistung (Teil 1)
Java-Leistung Kapitel 2 Ansatz für Leistungstests
Ich habe eine shopify App @java erstellt
Java
Java
Java-Leistung Kapitel 5 Grundlagen der Garbage Collection
GraalVM für Java-Leistung (Windows Developer Build)
Leistungseinbußen bei Java-Containern in der Menicoa-Umgebung
Stellen Sie JavaServlet-Apps lokal in Tomcat bereit
Erstellen Sie eine TODO-App in Java 7 Create Header
Lassen Sie uns eine Taschenrechner-App mit Java erstellen
Stellen Sie eine Java-Web-App für Heroku bereit
Java-Entwicklung mit Codenvy: Konsolen-App-Debug