[JAVA] Une histoire qui a fini par prendre une pause lors de l'utilisation de la liste liée avec une sensation de légèreté

Grosso modo

L'accès aléatoire aux données structurées en liste n'est pas autorisé. C'est une promesse avec mon frère!

Origine

Il y a quelques années, j'ai été contacté pour aider un système Java créé avec le soutien d'autres départements car ce serait incroyablement lent si j'y mettais un peu de big data.

Bon, si vous regardez la requête ou l'index pendant un moment, ça va être corrigé ... Je suis allé au support en me cueillant le nez.

Traitement du contenu

Le traitement de la partie lente était le suivant.

seulement ça? Oui c'est ça. Bien sûr, le traitement parallèle n'est pas une chose de grande classe.

Enquête d'infrastructure

Examinez ce que fait le serveur. L'infrastructure cette fois est une configuration typique à 3 couches et 3 serveurs.

Tout sur le serveur WEB peut se permettre. Le serveur AP a utilisé un processeur. Comme il s'agit d'un serveur à 14 cœurs (EC2 c4.4xlarge), il est triste que le taux d'utilisation soit de 7%, quelle que soit la dureté du processeur. Il y a une certaine charge disque sur le serveur de base de données, mais il y a une marge en termes de performances.

J'ai aussi étudié le réseau, la mémoire, etc., mais toutes les ressources sont en surplus. Diverses valeurs de réglage sont également normales.

Enquêter sur DB

Comme vous pouvez le voir, c'est un processus que seul INSERT est effectué. Par conséquent, même si je m'inquiétais de la charge CPU de l'AP, tout le monde sur place se méfiait de la base de données et dérangeait avec elle. Au final, avez-vous abordé le bug de OR Mapper? J'ai également eu une expérience nostalgique de l'utilisation directe de JDBC.

Cependant, il n'y a eu aucun résultat et le travail de vacances en colère de Rambo a été décidé ...

Découverte

Revenez à l'essentiel et refaites l'analyse du temps de traitement logique. Sous le témoignage que "je sens que le traitement devient plus lourd à mesure que le nombre de boucles progresse" J'ai décidé de découvrir la relation entre le nombre de boucles et le temps de traitement d'une boucle.

Voici une image des résultats de l'analyse. Nous avons modifié la quantité de données d'entrée et comparé 10 000 et 20 000 nairas. graph.png

** "La moitié après ... !!" **

Les plus petites données constituent la première moitié des plus grandes données, elles ne semblent donc pas fluctuer en fonction du contenu des données. Après une analyse plus approfondie, la ligne qui a pris le plus de temps en haut du graphique était: Le type de la variable «data» est «List ».

MyClass record = data.get(i);

J'ai été étonné de cela. Le simple fait d'obtenir les éléments de la liste est incroyablement lent. Quelqu'un a ouvert la bouche.

** "Ceci est une liste liée, n'est-ce pas?" **

Il a fallu énormément de temps pour récupérer le N10 000e de la liste liée, qui contient 2N millions d'enregistrements. Peut-être, sur la base de la moitié de la taille de la liste, les données de la dernière moitié sont accessibles par le bas.

Le problème qui nous a invité à faire une pause s'est terminé par un changement dans le niveau de refactoring consistant à changer l'instruction for en une instruction for étendue.

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

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

Quelle est la différence à première vue? Bien qu'il s'agisse d'un changement, pour List, accès aléatoire avant le changement, Après le changement, il est devenu un accès séquentiel (par Iterator), et lorsque le nombre de données était important, il y avait une grande différence de performances.

J'ai beaucoup appris.

La raison pour laquelle je n'ai pas utilisé l'instruction Extended for au début était que je voulais utiliser la valeur de i dans le processus. J'aimerais que Java ait une énumération Python ... (rancune)

Recommended Posts

Une histoire qui a fini par prendre une pause lors de l'utilisation de la liste liée avec une sensation de légèreté
Une histoire qui a eu du mal avec l'introduction de Web Apple Pay
L'histoire selon laquelle l'erreur de construction ne s'est pas arrêtée lors de l'utilisation d'Eclipse 2020
Une histoire à laquelle j'étais accro lors du test de l'API à l'aide de MockMVC
[Petite histoire Java] Surveiller lorsqu'une valeur est ajoutée à la liste
Une histoire dans laquelle j'étais vraiment quand j'ai fait triple DES avec ruby
Une histoire sur la création d'un Builder qui hérite du Builder
Une histoire sur l'exécution de Sprint-boot avec kubernetes (GKE) et l'échec de la connexion à CloudSQL
L'histoire lorsque le conteneur ne démarre pas avec docker-compose up et qu'une erreur se produit