2017-01-02 4 views
6

Je travaille avec un programme qui traite des fichiers, je peux faire plusieurs choses comme les renommer, lire le contenu d'entre eux, etc.RAM Trading par CPU (problème de performance)

Aujourd'hui, je suis initialisant comme suit:

return new Promise((resolve, reject) => { 
    glob("path/for/files/**/*", { 
    nodir: true 
    }, (error, files) => { 
    files = files.map((file) => { 
     // properties like full name, basename, extension, etc. 
    }); 
    resolve(files); 
    }); 
}); 

, je lis le contenu d'un répertoire spécifique, retourner tous les fichiers dans un tableau, puis utilisez la Array.map itérer sur le tableau et changer les chemins d'un objet avec des propriétés.

Parfois, je travaille avec 200 000 fichiers texte, donc cela devient un problème car il consomme trop de RAM. Donc, je veux remplacer par une fonction de construction avec chargement paresseux .. mais je n'ai jamais fait cela avant ... donc je cherche une main d'aide.

C'est mon code:

class File { 
    constructor(path) { 
    this.path = path; 
    } 

    extension() { 
    return path.extname(this.path); 
    } 
    // etc 
} 

Alors, ma question principale est: dois-je revenir que l'évaluation de la propriété, ou devrais-je le remplacer? Comme ceci:

extension() { 
    this.extension = path.extname(this.path); 
} 

Je comprends que c'est un compromis .. je vais au commerce de la mémoire par l'utilisation du processeur.

Merci.

+0

Que diriez-vous * pas * en utilisant des classes? Vous ne pouvez pas stocker les données de fichier dans des objets simples? – MaxArt

+0

Je stocke le fichier dans un tableau d'objets, et lequel est un objet. Je veux changer de classe pour améliorer l'utilisation de la mémoire. –

+0

@FXAMN Pourquoi croyez-vous que les classes vont réduire l'utilisation de la mémoire? – Raito

Répondre

0

Si vous voulez réduire l'utilisation de la RAM, je vous suggère de stocker un fichier méta-données supplémentaires pour chaque chemin, comme suit:

  1. Gardez les chemins en mémoire, ou certains d'entre eux, le cas échéant.

  2. propriétés Enregistrer les fichiers sur le disque dur

files.forEach((file) => { 
    // collect the properties you want for the file 
    // ... 
    var json = { path: file, extension: extension, .. } 

    // mark the metadata file so you can access it later, for example: put it in the same path with a suffix 
    var metaFile = path + '_meta.json'; 
    fs.writeFile(metaFile, JSON.stringify(json), (err) => { 
    if (err) throw err; 
    }); 
});

Maintenant, toutes les données méta est sur le disque dur. De cette façon, je crois, vous échangez de la mémoire pour l'espace disque et les appels CPU.

  1. Si vous souhaitez obtenir les propriétés d'un fichier, lisez simplement et JSON.parse son fichier de métadonnées correspondant.
0

Il n'y a aucune raison d'échanger du processeur pour l'espace. Il suffit de marcher sur l'arbre et de traiter les fichiers comme ils sont trouvés. L'espace nécessaire à la marche de l'arbre est proportionnel à la profondeur de l'arbre si la profondeur est atteinte en premier. Cela a presque certainement la même surcharge que la création de la liste des chemins dans votre code existant.

Pour la marche d'annuaire, le node.js FAQ recommande node-findit. La documentation y est assez claire. Votre code ressemblera à quelque chose comme:

var finder = require('findit')(root_directory); 
var path = require('path'); 
var basenames = []; 

finder.on('file', function (file, stat) { 
    basenames.push(path.basename(file)); 
    // etc 
} 

Ou vous pouvez envelopper les valeurs capturées dans un objet si vous le souhaitez.

0

Si vous stockez uniquement la propriété de chemin instance de classe NodeJS prenez pour votre exemple 200k * (path.length * 2 + 6) octets de mémoire.

Si vous voulez utiliser le chargement paresseux pour des noms de base, etc extenstions utiliser getters paresseux

class File { 
    constructor(path) { 
    this.path = path; 
    this._basename = null; 
    this._extname = null; 
    } 
    get extname() { 
    return this._extname || (this._extname = path.extname(this.path)); 
    } 
    get basename() { 
    return this._basename || (this._basename = path.basename(this.path)); 
    } 
}