J'écris une application nœud.js que STDOUT est pipiée dans un fichier. J'écris tout avec console.log. Après un moment, mon application atteint la limite de 1 Go et s'arrête. La chose intéressante est que si j'utilise la console.Error au lieu de console.log, l'utilisation de la mémoire est faible et le programme fonctionne bien. Donc, il semble que nœud.js ne puisse pas chasser le flux de stdout et tout est conservé en mémoire. Je veux garder STDRERR GRATUIT pour les erreurs. p>
Ma question est la suivante: p>
Y a-t-il un moyen d'écrire Blocking dans stdout? Ou du moins, puis-je écrire avec un rappel sur stdout afin que je puisse vous assurer que j'écris pas trop? P>
thx! p>
5 Réponses :
ne pas. p>
Ce que vous voulez faire est Vous voulez probablement utiliser le plus direct pause () code> Votre entrée lorsque la sortie est pleine, comme la méthode
pompe () code> fait, puis
CV () < / Code> Lorsque vous avez de la place pour écrire. Sinon, vos ballons de processus à la taille de Gargantuan. P>
SortiStream code> Stuff pour cela, cependant ou le
écrire () code> appel, pas
console.log () code>. p>
Bien que la question de la performance particulière n'est pas une excellente motivation pour cela, il existe absolument des situations où vous faire i> veulent utiliser une écriture bloquante à la console. Par exemple, si vous travaillez avec async_hooks code> Moniteurs, vous ne pouvez pas utiliser de méthodes asynchrones dans les rappels d'écoute ASYNC (puisque l'écriture déclenchera elle-même l'auditeur et recueil pour toujours).
Pause code> et
CV code> affecte la lecture, ne pas écrire.
Correct, mais c'est ce qui pousse la lecture et l'écriture de la boucle.
écrire en utilisant Si vous souhaitez que votre code ait l'air synchronisé, utilisez Streamlinejs comme décrit ici: noeud. JS Stdout Flush P> processus.stdout.write < / Code>
, la valeur de retour est de savoir si les données ont été tamponnées. Si c'est vrai, continuez à écrire lorsque processus.stdout code> émet l'événement code> drain code>. P>
Si vous voulez vraiment vraiment des écrivies synchrones à STDOUT, vous pouvez faire:
var fs = require('fs'); fs.writeSync(1, "Foo\n"); fs.fsyncSync(1);
C'est une excellente solution! Mais qu'est-ce que fs.fsyncsync (1) pour?
User698601: Assurez-vous que tout a été écrit sur le descripteur de fichier. L'un est stdout, deux est Stdrr, trois est Stdin.
On dirait que cette approche ne fonctionne pas lorsque la sortie de la tuyauterie sur stdout / stardr Stackoverflow.com/questions/50574243/... .
stdin est un descripteur de fichier zéro, pas trois
Edit: Comme indiqué par le commentateur, cette solution a un problème. PrintResolver pourrait être transformé en une matrice, mais à l'aide de la solution supérieure est beaucoup plus facile
une fonction d'impression synchrone qui fonctionne également avec des tuyaux AKA FIFO's, en utilisant ASYNC / AWAIT. Assurez-vous de toujours appeler "Imprimer" avec "Await Imprimer" P>
let printResolver; process.stdout.on('drain', function () { if (printResolver) printResolver(); }); async function print(str) { var done = process.stdout.write(str); if (!done) { await new Promise(function (resolve) { printResolver = resolve; }); } }
Si impression code> est appelé deux fois avant code> drain code> se produit, le global
printresolve code> sera remplacé et la promesse antérieure ne sera pas résolue.
Le problème (l'utilisation de la mémoire d'explosement) se produit probablement parce que votre programme crée une sortie plus rapidement qu'il ne peut être affiché. Par conséquent, vous voulez le manipuler. Votre question demande "Sortie synchrone", mais le problème peut en réalité être résolu en utilisant un code purement "asynchrone" (*) (*).
(* Note: Dans ce terme "asynchrone" est utilisé dans ce post. le sens "JavaScript-Single-thread". Qui diffère du sens "multi-thread" conventionnel qu'une bouilloire entièrement différente de poisson). strong> em> p> Cette réponse montre comment " Le code asynchrone "peut être utilisé avec des promesses pour empêcher l'utilisation de la mémoire d'exploser par" pause "(par opposition à bloquer) l'exécution jusqu'à ce que la sortie d'écriture ait été bouleversée avec succès. Cette réponse explique également comment une solution de code asynchrone peut être avantageuse par rapport à une solution de code synchrone. P> Q: "pause" sonne comme "bloqué" et comment le code asynchrone peut-il éventuellement "bloquer"? C'est un oxymoron! Em> p> A: Cela fonctionne car le moteur JavaScript V8 pause (blocs) Exécution de Seulement forte> La tranche de code unique attend une promesse asynchrone à compléter, Tout en permettant d'autres tranches de code à exécuter entre-temps. p> Voici une fonction d'écriture asynchrone (adaptée de ici ). p> Il peut être appelé à partir d'une fonction asynchreuse dans votre source code, par exemple où Plus de contexte est nécessaire pour voir clairement l'avantage sur une véritable écriture synchrone : exécutant le code ci-dessus ( cas 2 fort>) montrerait que l'utilisation de la mémoire n'explose toujours pas ( identique à cas 1 fort>) parce que la tranche associée code> enregistreuse code> a été suspendue, mais l'utilisation de la CPU était toujours parce que la tranche d'essentielle code> n'était pas en pause est bon (pensez covid). p> en comparaison, une solution synchrone bloquerait également le carrecteur essentiel code>. em> p> Que se passe-t-il avec Plusieurs tranches appelant Dans ce cas ( cas 3 fort>), l'utilisation de la mémoire est liée et le pourrait apparaître. p> p>
cas 1 fort> p> principal () code> est la seule fonction appelée à partir du niveau supérieur. L'utilisation de la mémoire n'explosera pas car elle serait si appelée
console.log ('Hello World'); code>. P>
cas 2 strong> p> streamwrite code>?
cas 3 fort> p> Essentialworker Code> L'utilisation du processeur est élevé, la même chose que dans Case 2 Strong>. Lignes individuelles de
Hello World Code> et
Goodbye World CODE> resterait atomique, mais les lignes ne remplaceraient pas proprement, par exemple p>