Pourquoi mon Node.js se bloque quand j'exécute de grands scripts ?

Je développe une API en Node.js avec Express et quand je teste avec de gros fichiers CSV (genre 500MB) le processus entier se bloque et je dois redémarrer. J'ai déjà essayé d'augmenter le heap mais ça continue à se bloquer. Quelqu'un sait si c'est vraiment un problème de mémoire ou si j'ai un truc qui cloche dans mon code ?

3 réponses

★ Meilleure réponse

J'ai des problèmes comme ça avec des bases de données énormes et c'est presque toujours la même raison : tu charges le fichier entier en mémoire avant de le traiter ! Un CSV de 500MB devient absolument monstrueux une fois parsé en arrays, et augmenter la heap c'est juste mettre un pansement sur une blessure. La vraie solution c'est d'utiliser les streams - tu traites ligne par ligne pendant que tu écris les données dans une base de données ou un fichier, et Node.js n'aura besoin de stocker que quelques KB à la fois ! Essaie avec la library `csv-parser` avec des streams ou même écrire un parser custom avec `fs.createReadStream()` et les événements, ça change complètement ton jeu.

J'ai vécu quelque chose de similaire quand j'ai essayé de traiter de gros fichiers d'un coup et j'ai réalisé que le problème n'était pas juste la mémoire - c'était le fait que je chargeais tout d'un coup en RAM. Avec un CSV de 500MB, si tu essaies de lire le fichier entier et ensuite le traiter, tu vas manquer de mémoire très vite. La solution c'est d'utiliser des streams au lieu de charger tout en mémoire. Dans Node.js tu as le module `fs.createReadStream()` qui te permet de lire le fichier petit à petit. Si tu utilises des bibliothèques comme `csv-parser`, tu peux enchaîner les streams pour traiter ligne par ligne sans surcharger la RAM.

Un truc qui a aussi changé pour moi c'est de réaliser que même avec les streams, si ta logique de traitement est lente (genre des opérations synchrones dans la boucle, des requêtes à la BD sans batch), tu vas créer un goulot d'étranglement. Quand le stream fournit les données plus vite que tu ne peux les traiter, la mémoire s'accumule quand même. Utilise `pause()` et `resume()` pour contrôler le flux, ou implémente correctement la contre-pression. Si tu fais des requêtes à la base de données pour chaque ligne, mets-les en batch - genre, groupe 1000 lignes et fais une seule opération au lieu de 1000 séparées.

C'est quoi plus ou moins l'opération que tu fais avec les données du CSV? Et tu sauvegardes les résultats quelque part (fichier, base de données) ou tu traites juste et tu renvoies par l'API? La réponse aide parce que le problème pourrait aussi venir de la façon dont tu envoies la réponse au client.

gabriel_oliveira asker Je traite les données et je les sauvegarde directement en base, sans batch. Je vais tester avec des streams et grouper les requêtes par lots de 1000, merci !

Le problème c'est probablement pas juste d'augmenter la heap, non. Quand tu charges un fichier de 500MB entier en mémoire avant de le traiter, Node.js s'étouffe même. Les gens ont raison de pointer ça, mais il y a un détail que personne n'a mentionné : si tu utilises des bibliothèques comme `csv-parser` ou similaires sans configurer les streams correctement, elle peut être en train de faire du buffer sur plusieurs lignes avant de traiter, ce qui aggrave tout. Tu dois utiliser les streams pour de vrai - `fs.createReadStream()` + un parser qui respecte les petits chunks. De cette façon Node.js traite ligne par ligne (ou en petits lots) sans faire exploser la mémoire.

Un autre truc qui tue : si tu fais des requêtes à la base de données dans la boucle de traitement du CSV, chaque ligne peut générer une requête séparée. Imagine 500 mille lignes = 500 mille requêtes. La base rame, la file d'attente grossit, la mémoire explose. Fais du batch - traite 1000 lignes d'un coup, fais un insert en lot, après tu passes aux suivantes. Avec des streams + batching tu peux traiter des fichiers beaucoup plus volumineux sans que ça gèle.

Votre réponse

Se connecterpour répondre.