调整 Node 流的 buffer 大小
- 原理:Node 流的
highWaterMark
属性决定了内部缓冲区的大小。较小的 highWaterMark
意味着流会在较少的数据量时触发背压,减少内存占用,但可能会导致读写操作更频繁。
- 代码示例:
const fs = require('fs');
const readableStream = fs.createReadStream('largeFile.txt', {
highWaterMark: 16384 // 设置 buffer 大小为 16KB
});
const writableStream = fs.createWriteStream('outputFile.txt');
readableStream.pipe(writableStream);
- 适用场景:当内存资源有限,对读写性能要求不是极高,希望平稳占用内存时适用。比如在老旧设备或资源紧张的服务器上处理大文件。
pipe 操作
- 原理:
pipe
方法用于将可读流的数据自动导向可写流,它会自动处理背压,优化数据流动。在 pipe
过程中,数据是逐块流动的,而不是一次性全部读入内存。
- 代码示例:
const fs = require('fs');
const readableStream = fs.createReadStream('largeFile.txt');
const writableStream = fs.createWriteStream('outputFile.txt');
readableStream.pipe(writableStream);
- 适用场景:适用于大多数大文件处理场景,因为它简洁高效,能在不同速度的流之间自动协调数据传输,减少手动处理背压的复杂性。例如日常的文件复制、日志处理等操作。
背压(backpressure)机制
- 原理:当可写流处理数据的速度慢于可读流产生数据的速度时,会发生背压。通过处理背压,可以防止可读流不断往内存中堆积数据。
- 代码示例:
const fs = require('fs');
const readableStream = fs.createReadStream('largeFile.txt');
const writableStream = fs.createWriteStream('outputFile.txt');
readableStream.on('data', (chunk) => {
const writeResult = writableStream.write(chunk);
if (!writeResult) {
readableStream.pause();
writableStream.once('drain', () => {
readableStream.resume();
});
}
});
- 适用场景:当可写流的写入速度明显慢于可读流的读取速度,且内存资源较为紧张时,需要手动精确控制背压,以避免内存溢出。比如在网络传输大文件到慢速设备时。