Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

387
Views
Escrituras en búfer en stdout en node.js

En node.js, se documenta que el flujo process.stdout se comporta "sincrónicamente", lo que, entre otras cosas, significa que cada llamada a stdout.write provoca una llamada al sistema de write inmediata, no hay almacenamiento en búfer. Por ejemplo

 import { stdout } from 'process'; for (let i = 1; i <= 1000; i++) { stdout.write(`line ${i}\n`); } stdout.end();

hace 1000 llamadas al sistema de write . Esto no es lo que desea cuando está escribiendo una utilidad de emisión de datos tradicional de Unix. Es posible omitir process.stdout y crear una secuencia de escritura separada que se hunda en el descriptor de archivo 1, por ejemplo

 import { stdout } from 'process'; import { createWriteStream } from 'fs'; let ostream = createWriteStream("/ignored", { fd: stdout.fd }); for (let i = 1; i <= 1000; i++) { ostream.write(`line ${i}\n`); } ostream.end();

hace una sola llamada al sistema. Sin embargo, los desvíos como este son peligrosos: después de la llamada ostream.end , el descriptor de archivo 1 se cierra pero el objeto process.stdout no lo sabe.

¿Hay alguna forma oficial de obtener una salida almacenada en búfer cuando se usa process.stdout ? Ideal en mi libro sería algo como el setvbuf de C.

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

También puede llamar a .end() en stdout. No estoy seguro de si esto lo hace más seguro.

 import { promisify } from 'util'; import stream from 'stream'; import { stdout } from 'process'; import { createWriteStream } from 'fs'; const finished = promisify(stream.finished); let ostream = createWriteStream("/ignored", { fd: stdout.fd }); for (let i = 1; i <= 1000; i++) { ostream.write(`line ${i}\n`); } ostream.end(); await finished(ostream).then(()=> { console.log('Not quite done.'); stdout.end() console.log('Not gonna see this.'); });

EDITAR: acabo de leer en los documentos de Node que en los sistemas POSIX, si usa tuberías para enviar datos a la salida estándar, es asíncrono. Así que el siguiente código debería funcionar:

 import { stdout } from 'process'; import { Readable } from 'stream'; const data = new Readable() data._read = () => {}; data.pipe(stdout); for (let i = 1; i <= 1000; i++) { data.push(`line ${i}\n`); }
over 4 years ago · Santiago Trujillo Report

0

Utilice process.stdout.cork()

El método writable.cork() obliga a que todos los datos escritos se almacenen en la memoria. Los datos almacenados en el búfer se eliminarán cuando se llame a los métodos stream.uncork() o stream.end().

Nota: esto también console.log() .

 process.stdout.cork(); for (let i = 1; i <= 1000; i++) { process.stdout.write(`line ${i}\n`); } process.stdout.uncork();

O, si desea vaciar el búfer cada vez que se alcanza el ciclo de eventos, puede anular write() :

 const { stdout } = process; const { write } = stdout; stdout.write = function() { if (this.writableCorked == 0) { this.cork(); process.nextTick(() => this.uncork()); } write.apply(this, arguments); } for (let i = 1; i <= 1000; i++) { process.stdout.write(`line ${i}\n`); }

Si le preocupa que el búfer se vuelva demasiado grande, también puede consultar stdout.writableNeedDrain .

strace -f -c -e trace=write,writev resultados:

 % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 100.00 0.000006 1 4 write 0.00 0.000000 0 1 writev ------ ----------- ----------- --------- --------- ---------------- 100.00 0.000006 5 total

Probado usando el nodo v16.13.2

over 4 years ago · Santiago Trujillo Report

0

Después de pensar un poco más en esto, la forma ideal de configurar el uso de process.stdout de manera segura y eficiente para la salida de datos masivos sería STDOUT_FILENO dup envolver un fs.WriteStream normal alrededor del duplicado y luego dup2 STDERR_FILENO sobre STDOUT_FILENO , lo que haría que todos los métodos del objeto de consola global y process.stdout escribieran en stderr en lugar de stdout. (Por lo que puedo decir, no hay otra forma de hacerlo). El código que genera los datos masivos luego escribiría en WriteStream normal en lugar de procesar.stdout.

O, en código:

 import * as fs from "fs/promises"; import process from "process"; async function prepare_buffered_stdout(options) { options ??= {}; const stdout_copy = await fs.dup(process.stdout.fd); await fs.dup2(process.stderr.fd, process.stdout.fd); return fs.fdopen(stdout_copy, "w").createWriteStream(options); }

Desafortunadamente, existe el problema menor de que las funciones fs.dup , fs.dup2 y fs.fdopen no existen. He presentado una solicitud de función para que se agreguen .

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!