1

我正在编写非常简单的应用程序来转换数据 - 读取一个文件并写入另一个文件。文件相对较大 - 2 GB。然而,我发现刷新到文件系统并没有发生,在软木-松开循环中,它只发生在 end() 上,所以 end() 基本上会挂起系统,直到它完全刷新。我简化了示例,因此它只是多次向流中写入一行。

var PREFIX = 'E:\\TEST\\';
var line = 'AA      11     999999999       20160101        123456  20160101                AAA     00      00   00      0       0       0       2       2       0       0       20160101        0       00';
var fileSystem = require('fs');


function writeStrings() {
var stringsCount = 0;
var stream = fileSystem.createWriteStream(PREFIX +'output.txt');
stream.once('drain', function () {
    console.log("drained");
});

stream.once('open', function (fileDescriptor) {
    var started = false;
    console.log('writing file ');
    stream.cork();
    for (i = 0; i < 2000000; i++) {
        stream.write(line + i);
        if (i % 10000 == 0) {
//                console.log('passed ',i);
        }
        if (i % 100000 == 0) {
            console.log('uncorcked ',i,stream._writableState.writing);
            stream.uncork();
            stream.cork();
        }

    }
    stream.end();
});

stream.once('finish', function () {
    console.log("done");
});

}

writeStrings();

进入节点 _stream_writable.js,我发现它只在这种情况下刷新缓冲区:

    if (!state.writing &&
    !state.corked &&
    !state.finished &&
    !state.bufferProcessing &&
    state.buffer.length)
  clearBuffer(this, state);

而且,正如您从示例中看到的那样,在第一次 uncork() 之后写入标志不会设置,这会阻止 uncork 刷新。另外,我根本没有看到排水事件发生。玩 highWaterMark 没有帮助(实际上似乎对任何事情都没有影响)。手动将写入设置为 false(+ 其他一些标志)确实有帮助,但这肯定是错误的。我误解了这个概念吗?

4

2 回答 2

2

从 node.js 文档中我发现 uncork() 的数量应该与 cork() 调用的数量相匹配,我没有看到匹配的 stream.uncork() 调用在 for 循环之前调用 stream.cork()。这可能是问题所在。

于 2016-11-06T17:10:32.080 回答
0

查看nodejs.org上的指南,您不应该stream.uncork()在同一个事件循环中调用两次。这是一段摘录:

// Using .uncork() twice here makes two calls on the C++ layer, rendering the
// cork/uncork technique useless.
ws.cork();
ws.write('hello ');
ws.write('world ');
ws.uncork();

ws.cork();
ws.write('from ');
ws.write('Matteo');
ws.uncork();

// The correct way to write this is to utilize process.nextTick(), which fires
// on the next event loop.
ws.cork();
ws.write('hello ');
ws.write('world ');
process.nextTick(doUncork, ws);

ws.cork();
ws.write('from ');
ws.write('Matteo');
process.nextTick(doUncork, ws);

// as a global function
function doUncork(stream) {
  stream.uncork();
}

.cork()可以调用任意多次,我们只需要小心调用.uncork()相同的次数以使其再次流动。

于 2018-01-05T09:12:15.980 回答