NODEJS:可写流上的Uncork()方法并没有真正刷新数据

时间:2016-01-20 14:22:16

标签: node.js node.js-stream

我正在编写非常简单的应用程序来转换数据 - 读取一个文件并写入另一个文件。文件相对较大 - 2 GB。但是,我发现在文件系统中没有发生冲洗,在cork-uncork循环中,它只发生在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()之后没有设置回来,这会阻止拔出冲洗。 另外,我根本没有看到排水事件。玩highWaterMark并没有帮助(实际上似乎没有任何效果)。手动将写入设置为false(+其他一些标志)确实有帮助,但这肯定是错误的。 我误解了这个概念吗?

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分: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()相同的时间以使其再次流动。