10
votes

Fuite de la mémoire dans le nœud.js grattoir

Ceci est un grattoir simple écrit en JavaScript avec node.js, pour racler Wikipedia pour les données périodiques d'élément de table. Les dépendances sont JSDOM pour la manipulation DOM et bande-gang pour faire la queue.

Cela fonctionne bien, la plupart du temps (il ne gère pas les erreurs gracieusement) et le code n'est pas trop mauvais, osez-moi dire pour une tentative de tentative, mais il y a une grave faute avec elle - il fuit la mémoire Heure horriblement, entre 0,3% et 0,6% de la mémoire de l'ordinateur pour chaque élément, de sorte que, au moment où il conduit à conduire, il utiliserait quelque part près de 20%, ce qui est clairement inacceptable.

J'ai essayé de travailler avec des profilers, mais je ne les ai pas trouvés pour être utiles ou avoir de la difficulté à interpréter les données. Je soupçonne que cela a quelque chose à voir avec le chemin Processelement est transmis, mais j'ai du mal à réécrire le code de la file d'attente dans quelque chose de plus élégant. xxx


0 commentaires

4 Réponses :


0
votes

Je sais que ce n'est pas une bonne de réponse, mais j'ai eu un problème similaire. J'ai plusieurs racleurs fonctionnant simultanément et que la mémoire était devenue futée.

J'ai fini par utiliser Node-JQuery au lieu de JSDOM

https://github.com/coolaj86/node-jQuery


2 commentaires

Nope, j'avais effectivement remplacé nœud-jQuery avec JSDDY tout simplement - les deux fuites de la mémoire de manière étonnamment similaire


Pourquoi pensez-vous que ce n'est pas votre code qui fuit de la mémoire? Changer la bibliothèque ne vous aidera probablement pas.



24
votes

JSDDD a une fuite de mémoire qui provient de la copie dans et de copier la logique derrière le noeud vm.runincontext () . Il a été effort de résoudre ce problème à l'aide de C ++ et nous espérons prouver la solution avant de tenter de la pousser dans le nœud.

Une solution de contournement pour le moment est de reproduire un processus enfant pour chaque DOM et de le fermer lorsque vous avez terminé.

EDIT:

AS de JSDDOM 0.2.3 Ce problème est fixé tant que vous fermez la fenêtre ( window.flose () ) lorsque vous en avez terminé.


2 commentaires

Window.Close () est précisément correct, assurez-vous que vous fermez votre fenêtre une fois que vous avez terminé et que le GC fonctionnera comme prévu. :)


Si vous me permettez: vous devez inclure cela sur le fichier de frontpage sur GitHub. Je pense que c'est assez important pour l'utilisateur de savoir que l'objet de la fenêtre doit être nettoyé! Peut-être que son "évident" mais pour moi, ce n'était pas;).



4
votes

Je pense que j'ai un meilleur travail - autour, réutilisez votre instance de JSDOM en définissant la propriété window.document.innerhtml. Résolu mes problèmes de fuite de mémoire!

    // jsdom has a memory leak when using multiple instance
    // cache a single instance and swap out innerHTML
    var dom = require('jsdom');
    var win;
    var useJQuery = function(html, fnCallback) {
        if (!win) {
            var defEnv = {
                html:html,
                scripts:['jquery-1.5.min.js'],
            };
            dom.env(defEnv, function (err, window) {
                if (err) throw new Error('failed to init dom');
                win = window;
                fnCallback(window.jQuery);
            });
        }
        else {
            win.document.innerHTML = html;
            fnCallback(win.jQuery);
        }
    };
    ....
    // Use it!
    useJQuery(html, function($) { $('woohoo').val('test'); });


1 commentaires

Cela n'a pas vraiment fonctionné pour moi, Heres mon extrait qui fonctionne: var jsdom = nécessite ('JSDOM'); var win = jsdom.jsdom (). Creewindow (); Var usejQuery = fonction (HTML, FnCallback) {jsdom.jquéry.jquéry (gagnez " code.jquery.com/jquery .js ", fonction () {win.document.innerhtml = html; fncallback (win);}); };



11
votes

Pour traitement HTML de type JQuery avec le nœud que j'utilise maintenant cheerio au lieu de JSDOM. Jusqu'à présent, je n'ai vu aucune fuite de mémoire lors de la mise au rebut et de l'analyse de 10 000 pages pendant quelques heures.


2 commentaires

C'est un bon conseil. J'ai eu un certain code qui a essayé d'analyser un HTML d'environ 25 mégaoctets et JSDOM s'est écrasé après un long délai avec une erreur de mémoire de mémoire. Réécrivez le code pour utiliser Cheerio le code terminé en 7 secondes sans aucune erreur.


À l'étape actuelle, Cheerio est très différent de JQuery et manque de nombreuses fonctionnalités dans les sélecteurs et les wrappers Dom. C'est certainement plus rapide, mais pas compatible, qui est un problème si vous avez besoin de la familiarité et de l'expressivité de JQuery.