9
votes

Dans Node.js Utilisation de JSON.Stringify Résultats dans l'erreur 'Traitement hors de la mémoire'

Avec noeud, j'essaie de collecter des données utilisateur à partir d'un serveur LDAP, puis d'écrire ces données dans un fichier JSON. J'utilise le code suivant pour le faire:

var ldap = require('ldapjs');
var util = require('util');
var fs = require('fs');
var client = ldap.createClient({
  url: '************'
});

client.bind('CN=**********,OU=Users,OU=LBi UK,OU=UK,DC=********,DC=local', '*********', function(err) {
  if (err) {
    console.log(err.name);
  }
});


// taken from http://ldapjs.org/client.html
client.search('OU=Users,OU=******,OU=UK,DC=******,DC=local', {
  scope: 'sub',
  filter: 'objectClass=organizationalPerson',
  attributes: ['givenName', 'dn', 'sn', 'title', 'department', 'thumbnailPhoto', 'manager']
  // filter by organizational person
}, function(err, res) {
  if (err) {
    console.log(err.name);
  }

  var limit = 1;
  var data = {"directory": []};

  res.on('searchEntry', function(entry) {

    var obj = {};
    entry.attributes.forEach(function (attribute) {
      var value;
      if (attribute.type === 'thumbnailPhoto') {
        value = attribute.buffers[0];

      } else {
        value = attribute.vals[0];
      }
      obj[attribute.type] = value;
    });
    data.directory.push(obj);
  });
  res.on('error', function(err) {
    console.log('error: ' + err.message);
  });
  res.on('end', function(result) {
    fs.writeFile('data.json', JSON.stringify(data, null, 4));
  });

});


7 commentaires

Avez-vous considéré que ... vous êtes hors de mémoire? :) C'est à dire. Les données sont trop grandes?


@freakish Je ne sais pas si c'est le cas parce que je sais que quelqu'un d'autre a pu écrire les données dans un fichier. Cependant, quand je lui ai expliqué, je reçois cette erreur qu'il avait dit qu'il n'avait pas rencontré ce problème. Existe-t-il une façon de pouvoir augmenter la quantité de mémoire disponible?


Ouais, achetez plus de RAM. :) ou tuez d'autres applications. L'autre personne a-t-elle fait cela sur la même machine? Sinon, vous ne pouvez pas le comparer. Je pense que cela est aussi simple que cela: vous êtes hors de mémoire. Pour gérer ce problème (sans obtenir plus de RAM), vous devez diviser les données en pièces plus petites et gérer une pièce à la fois.


@freakish, je viens d'essayer d'utiliser console.log (util.inspect (données)); au lieu de fs.writefile et j'ai pu afficher les données dans la console sans problème . Y a-t-il une alternative à JSON.Stringify que je peux utiliser pour écrire le fichier?


Stephen, vous ne semblez pas comprendre. Vous avez suffisamment de mémoire pour détenir l'objet et l'inspecter, mais la stringification crée en fait une nouvelle chaîne en mémoire. Étant donné que vos données sont assez grandes, cette chaîne ne correspond pas à la mémoire. La modification de la bibliothèque ne vous aidera pas, car à la fin, vous souhaitez contenir la grande chaîne dans la mémoire. Et vous ne devriez pas. Comme je vous l'ai dit: vous devez diviser les données en parties plus petites, stringifiez ces pièces et appendez-la dans une pièce de fichier par pièce. Bien sûr, je pourrais avoir tort, mais je ne peux pas voir l'autre explication logique.


@freakish ah ok merci pour votre aide. Je vais essayer de tes suggestions.


Vous avez besoin d'une bibliothèque JSON.Stringify Streaming.


3 Réponses :


1
votes

Quelque chose se passe récursivement.

Assurez-vous que votre objet DATA ne contient aucune référence circulaire, telle que ce ou quoi que ce soit d'autre qui a du mal à être sérialisé.


3 commentaires

JSON.Stringify devrait causer TypeError: convertir la structure circulaire à JSON si la structure a des références circulaires.


@Esailija: Il doit littéralement être un problème de mémoire alors.


Je ne pense pas que ce soit le cas. Les structures circulaires lancent typeError lorsque vous essayez de les limiter.



5
votes

Comme @freakish a mentionné le problème, mes données étaient trop grandes.

La raison pour laquelle les données étaient si importantes étaient dues à un grand nombre d'images qui étaient renvoyées comme des objets. À la fin, tout ce que je devais faire était de coder l'objet comme base64 à l'aide de tampons, puis la taille des données est devenue beaucoup plus gérable.


0 commentaires

2
votes

Les données de Stephen n'étaient pas "trop ​​grandes". Ceci est un bogue dans le nœud, suivi ici , et pas complètement corrigé. Je le vois toujours 2 ans plus tard, avec un objet de complexité constante produisant parfois l'erreur OOM, mais la plupart du temps étant écrit avec succès sur le disque.

Une solution de contournement est de rechercher une bibliothèque Streaming JSon Writer comme JSON-Ecrire (de l'auteur D3 Mike Bostock).


0 commentaires