[JAVA] Eine Geschichte, die eine Pause einlegte, wenn sie Linked List mit einem leichten Gefühl benutzte

Grob gesagt

Der wahlfreie Zugriff auf Daten mit Listenstruktur ist nicht zulässig. Es ist ein Versprechen mit meinem Bruder!

Ursprung

Vor einigen Jahren wurde ich kontaktiert, um einem Java-System zu helfen, das mit Unterstützung einer anderen Abteilung erstellt wurde, da es unglaublich langsam wäre, wenn ich ein wenig Big Data hineinstecken würde.

Nun, wenn Sie sich die Abfrage oder den Index für einen Moment ansehen, wird dies behoben ... Ich ging zur Unterstützung, während ich meine Nase pflückte.

Inhalte verarbeiten

Die Verarbeitung des langsamen Teils war wie folgt.

nur das? Ja das ist es. Parallelverarbeitung ist natürlich keine hochklassige Sache.

Infrastrukturerhebung

Untersuchen Sie, was der Server tut. Die Infrastruktur ist diesmal eine typische 3-Layer-3-Server-Konfiguration.

Alles auf dem WEB-Server kann es sich leisten. Der AP-Server hat eine CPU verbraucht. Da es sich um einen 14-Core-Server (EC2 c4.4xlarge) handelt, ist es traurig, dass die Nutzungsrate 7% beträgt, egal wie hart eine CPU arbeitet. Auf dem DB-Server ist eine gewisse Festplattenlast vorhanden, die Leistung ist jedoch begrenzt.

Ich habe auch das Netzwerk, den Speicher usw. untersucht, aber alle Ressourcen sind überschüssig. Verschiedene Einstellwerte sind ebenfalls normal.

Untersuchen Sie die DB

Wie Sie sehen können, wird nur INSERT ausgeführt. Obwohl ich mir Sorgen um die CPU-Auslastung des AP machte, waren alle vor Ort misstrauisch gegenüber der Datenbank und spielten damit herum. Haben Sie am Ende den Fehler von OR Mapper behoben? Ich hatte auch eine nostalgische Erfahrung mit der direkten Verwendung von JDBC.

Es gab jedoch kein Ergebnis und Rambos verärgerte Urlaubsarbeit wurde entschieden ...

Entdeckung

Kehren Sie zu den Grundlagen zurück und wiederholen Sie die Analyse der Logikverarbeitungszeit. Unter dem Zeugnis, dass "ich das Gefühl habe, dass die Verarbeitung mit fortschreitender Anzahl von Schleifen schwerer wird" Ich beschloss, die Beziehung zwischen der Anzahl der Schleifen und der Verarbeitungszeit einer Schleife herauszufinden.

Das Folgende ist ein Bild der Analyseergebnisse. Wir haben die Menge der Eingabedaten geändert und N10.000 und 20.000 verglichen. graph.png

** "Die Hälfte danach ... !!" **

Die kleineren Daten sind die erste Hälfte der größeren Daten, sodass sie je nach Inhalt der Daten nicht zu schwanken scheinen. Bei näherer Betrachtung war die Linie am oberen Rand des Diagramms die Zeit, die am meisten Zeit in Anspruch nahm: Der Typ der Variablen data ist List <MyClass>.

MyClass record = data.get(i);

Ich war erstaunt darüber. Nur die Elemente aus der Liste zu bekommen, ist wahnsinnig langsam. Jemand öffnete den Mund.

** "Dies ist eine verknüpfte Liste, nicht wahr?" **

Das Abrufen des 10.000sten N der verknüpften Liste mit 2N Millionen Datensätzen hat enorm viel Zeit in Anspruch genommen. Basierend auf der halben Größe der Liste wird möglicherweise von unten auf die Daten in der zweiten Hälfte zugegriffen.

Die Probleme, die uns zu einer Pause einluden, endeten mit einer Änderung der Refactoring-Ebene, bei der die for-Anweisung in eine erweiterte for-Anweisung geändert wurde.

for (int i = 0; i < data.size(); i++) {
    MyClass record = data.get(i);
    ...
}

int i = 0;
for (MyClass record: data) {
    ...
    i++;
}

Was ist der Unterschied auf den ersten Blick? Obwohl es sich um eine Änderung handelt, wird für List vor der Änderung ein Direktzugriff ausgeführt. Nach der Änderung wurde es zu einem sequentiellen Zugriff (von Iterator), und wenn die Anzahl der Daten groß war, gab es einen großen Leistungsunterschied.

Ich habe viel gelernt.

Der Grund, warum ich die erweiterte for-Anweisung zuerst nicht verwendet habe, war, dass ich den Wert von i in diesem Prozess verwenden wollte. Ich wünschte, Java hätte eine Python-Aufzählung ... (Groll)

Recommended Posts

Eine Geschichte, die eine Pause einlegte, wenn sie Linked List mit einem leichten Gefühl benutzte
Eine Geschichte, die mit der Einführung von Web Apple Pay zu kämpfen hatte
Die Geschichte, dass der Erstellungsfehler bei Verwendung von Eclipse 2020 nicht aufgehört hat
Eine Geschichte, der ich beim Testen der API mit MockMVC verfallen war
[Java small story] Überwachen Sie, wann der Liste ein Wert hinzugefügt wird
Eine Geschichte, die mir sehr gut gefallen hat, als ich mit Ruby Triple DES gemacht habe
Eine Geschichte über das Erstellen eines Builders, der den Builder erbt
Die Geschichte, Sprint-Boot mit Kubernetes (GKE) auszuführen und keine Verbindung zu CloudSQL herzustellen
Die Geschichte, wenn der Container nicht mit Docker-Compose gestartet wird und ein Fehler auftritt