当输入流通过管道传输到多个输出流时,缓冲区级别会发生什么?
What would happens on buffer level when an input stream piping to multi output streams?
我正在阅读流文档并在 https://nodejs.org/api/stream.html#stream_buffering
寻找关于流的缓冲行为描述
该文档似乎没有提到当管道传输到多个输出时 inputStream 缓冲区(或缓冲区?)会发生什么,因为不同的输出具有不同的消耗速度:
当管道传输多个输出时,readableStream 是否为每个输出保留专用缓冲区?
消耗时输出是保持相同的速度还是更快的会提前结束?
const input = fs.createReadStream('img.jpg');
const target1 = input.pipe(fs.createWriteStream('target1.jpg'));
const target2 = input.pipe(fs.createWriteStream('target2.jpg'));
TL;DR: 简短的回答是 - 较慢的目标流控制流速。
所以首先让我们看看读取端发生了什么。
const input = fs.createReadStream('img.jpg');
当您实例化输入流时,它以暂停模式创建并计划读取(没有同步完成读取,因此它还不会访问文件)。流已将 highWaterMark
设置为类似 16384
的值,并且当前具有 0 字节的缓冲区。
const target1 = input.pipe(fs.createWriteStream('target1.jpg'));
const target2 = input.pipe(fs.createWriteStream('target2.jpg'));
现在,当您实际将其通过管道传输到可写流时,通过在 pipe method implementation - see the source.
中添加 on('data')
事件处理程序来设置流动模式
完成后,我假设没有更多程序到 运行,因此节点开始实际读取并 运行s 上面处理程序中的计划代码,它简单地写入通过的任何数据.
当任何目标要写入的数据多于其 highWaterMark
时,流量控制就会发生,这会将 write
操作转移到 return false
。然后读数被 calling pause here in the code 停止。在此之上两行,您会看到 state.awaitDrain 增加了。
现在读取流再次 paused
并且可写流正在将字节写入磁盘 - 在某些时候缓冲区级别再次低于 highWaterMark
。此时会触发一个 drain
事件,该事件 executes this line 并且在调用 所有等待的排水管 之后,恢复流程。这是通过检查递减的 awaitDrain
属性 是否已达到零来完成的,这意味着所有等待的耗尽事件都已被调用。
在上述情况下,两个流中较快的一个在写入时可能 return 是一个假值,但它肯定会像第一个流一样耗尽。如果不是 awaitDrain
,更快的流将恢复数据流,这可能会导致两者中较慢的缓冲区溢出。
我正在阅读流文档并在 https://nodejs.org/api/stream.html#stream_buffering
寻找关于流的缓冲行为描述该文档似乎没有提到当管道传输到多个输出时 inputStream 缓冲区(或缓冲区?)会发生什么,因为不同的输出具有不同的消耗速度:
当管道传输多个输出时,readableStream 是否为每个输出保留专用缓冲区?
消耗时输出是保持相同的速度还是更快的会提前结束?
const input = fs.createReadStream('img.jpg');
const target1 = input.pipe(fs.createWriteStream('target1.jpg'));
const target2 = input.pipe(fs.createWriteStream('target2.jpg'));
TL;DR: 简短的回答是 - 较慢的目标流控制流速。
所以首先让我们看看读取端发生了什么。
const input = fs.createReadStream('img.jpg');
当您实例化输入流时,它以暂停模式创建并计划读取(没有同步完成读取,因此它还不会访问文件)。流已将 highWaterMark
设置为类似 16384
的值,并且当前具有 0 字节的缓冲区。
const target1 = input.pipe(fs.createWriteStream('target1.jpg'));
const target2 = input.pipe(fs.createWriteStream('target2.jpg'));
现在,当您实际将其通过管道传输到可写流时,通过在 pipe method implementation - see the source.
中添加on('data')
事件处理程序来设置流动模式
完成后,我假设没有更多程序到 运行,因此节点开始实际读取并 运行s 上面处理程序中的计划代码,它简单地写入通过的任何数据.
当任何目标要写入的数据多于其 highWaterMark
时,流量控制就会发生,这会将 write
操作转移到 return false
。然后读数被 calling pause here in the code 停止。在此之上两行,您会看到 state.awaitDrain 增加了。
现在读取流再次 paused
并且可写流正在将字节写入磁盘 - 在某些时候缓冲区级别再次低于 highWaterMark
。此时会触发一个 drain
事件,该事件 executes this line 并且在调用 所有等待的排水管 之后,恢复流程。这是通过检查递减的 awaitDrain
属性 是否已达到零来完成的,这意味着所有等待的耗尽事件都已被调用。
在上述情况下,两个流中较快的一个在写入时可能 return 是一个假值,但它肯定会像第一个流一样耗尽。如果不是 awaitDrain
,更快的流将恢复数据流,这可能会导致两者中较慢的缓冲区溢出。