2 votes

besoin d'un moyen de contourner l'erreur "nœud manquant de mémoire".

J'analyse ~250K XML et charge les données dans une base de données SQLite. Je suis en train d'utiliser la version 10.15.1 de node avec cheerio y better-sqlite3 sur un ordinateur portable Mac OS X avec 8 Go de mémoire. Je suis readdirSync -L'analyse de tout le dossier de ~250K fichiers, l'analyse des fichiers XML et le chargement des données extraites en utilisant des transactions par lots de 10K. J'utilise --max_old_space_size=4096 mais on obtient toujours le FATAL ERROR : Ineffective mark-compacts près de la limite du tas L'allocation a échoué - le tas de JavaScript n'a plus de mémoire. .

Maintenant, si je traite 100K fichiers, puis quitte le nœud, puis recommence et traite les ~150K fichiers restants, alors tout fonctionne. Mais, je préférerais le faire en une seule fois car c'est quelque chose qui doit être fait sans surveillance. Y a-t-il autre chose que je puisse faire compte tenu de mes contraintes ? Je ne peux pas utiliser une machine avec plus de mémoire car je n'y ai pas accès. Je pourrais essayer d'augmenter le --max_old_space_size un peu plus, ou je pourrais essayer de faire de plus petits lots de transactions, mais je ne suis pas sûr que cela aide (j'ai essayé avec 8000 fichiers par transaction au lieu de 10K, mais cela aussi a manqué de mémoire). La seule chose qui semble aider pour le moment est de quitter le nœud entre les deux. Y a-t-il un moyen de simuler cela ? C'est-à-dire, dire au nœud de libérer toute la mémoire et prétendre qu'il a été redémarré ? D'autres idées ?

0voto

punkish Points 1517

J'ai finalement trouvé un moyen de contourner mon problème (j'utilise le terme "par hasard" car je ne suis pas sûr que ce soit la bonne stratégie, mais elle fonctionne pour moi).

J'ai découvert qu'en augmentant le --max_old_space_size La valeur ne m'a pas vraiment aidé. De toute façon, comme je l'ai mentionné plus haut, mon MacBook n'a que 8 Go, donc ma limite est de toute façon basse. À l'inverse, ce qui m'a aidé, c'est de réduire simplement la taille de mon lot. Ainsi, au lieu de traiter 10K XML, de stocker leurs données en mémoire, puis de les insérer dans une transaction dans SQLite, j'ai traité 1K XML à la fois. Bien sûr, pour traiter ~250K fichiers, je devais maintenant gérer 250 boucles au lieu de 25, mais cela n'a pas trop augmenté mon temps. J'ai constaté que le temps de traitement est assez linéaire, environ 5K ms pour 1K fichiers (ou 50K ms pour 10K fichiers). SQLite est assez rapide, que je lui envoie 1K ou 10K INSERTs dans une transaction, mais c'est mon processus d'analyse XML qui commence à faire des siennes lorsqu'il s'agit de très grandes quantités de données. En fait, ce n'est peut-être pas non plus un problème de cheerio (que j'ai trouvé très bon). C'est peut-être juste mon style de codage qui peut être amélioré de beaucoup.

En tout état de cause, le traitement de 1K transactions avec une --max_old_space_size=2048 a fait le travail pour moi. L'utilisation de la mémoire par nœud (comme indiqué dans Moniteur d'activité était assez stable, et le dump complet de 250K fichiers a été analysé et chargé dans la base de données en 42 minutes environ. Je peux vivre avec ça.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X