2016-01-20 2 views
1

Я пишу довольно простое приложение для преобразования данных - читайте один файл и пишите на другой. Файлы относительно большие - 2 ГБ. Тем не менее, я обнаружил, что флеш в файловой системе не происходит, в цикле пробки-пробки это происходит только в конце(), поэтому end() в основном зависает системой до тех пор, пока она полностью не погаснет. Я упростил пример, поэтому он просто пишет строку в поток много раз.NODEJS: метод Uncork() для записываемого потока на самом деле не очищает данные

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 (+ некоторые другие флаги) действительно помогло, но это, безусловно, неправильно. Я не понимаю концепцию этого?

+0

Я собирался сказать, что вам нужно вызвать первый 'stream.cork()' вне цикла 'for', но, судя по вашему редактированию, это уже реальная ситуация? – robertklep

+0

Да, действительно. На самом деле я сейчас не вижу «открытое» событие в документации на узел, и я просто брожу туда, где я его принимаю. Однако остается вопрос - как можно просто написать кучу строк внутри файла, контролируя промывку? Потому что он делает то, что делает, но только один раз. – Andrey

+0

Не смотря на это слишком глубоко, я думаю, что это связано с написанием, поэтому 'uncork()', будучи асинхронным. Пока собранный буфер все еще записывается, ваш код продолжает работать (следовательно, флаг 'writing' является истинным). Кроме того, насколько я понимаю документы, «утечка» испускается, когда безопасно писать, а не когда внутренний буфер, используемый для 'cork()', был исчерпан. – robertklep

ответ

1

Из документации node.js я обнаружил, что число uncork() должно соответствовать количеству вызовов cork(), я не вижу соответствующего вызова stream.uncork() для stream.cork(), который вызывается до цикл for. Это может быть проблемой.

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() одинаковое количество раз, чтобы сделать его поток снова.

Смежные вопросы