Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

383
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar

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 Denunciar

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda