проблема
Я пытаюсь просканировать каталог диска (рекурсивно пройтись по всем путям) и записать все пути в файл (как он их находит), используя fs.createWriteStream
, чтобы сохранить низкое использование памяти, но это не работает, использование памяти достигает 2 ГБ во время сканирования.
ожидаемый
Я ожидал, что fs.createWriteStream
будет автоматически обрабатывать использование памяти/диска в любое время, сохраняя использование памяти на минимальном уровне с обратным давлением.
Код
const fs = require('fs')
const walkdir = require('walkdir')
let dir = 'C:/'
let options = {
"max_depth": 0,
"track_inodes": true,
"return_object": false,
"no_return": true,
}
const wstream = fs.createWriteStream("C:/Users/USERNAME/Desktop/paths.txt")
let walker = walkdir(dir, options)
walker.on('path', (path) => {
wstream.write(path + '\n')
})
walker.on('end', (path) => {
wstream.end()
})
Это потому, что я не использую .pipe()
? Я попытался создать new Stream.Readable({read{}})
а затем внутри .on('path'
эмиттер проталкивает пути в него с помощью readable.push(path)
но это не сработало.
ОБНОВИТЬ:
Способ 2:
Я попробовал предложенный метод drain
ответов, но он мало помогает, он уменьшает использование памяти до 500 МБ (что все еще слишком много для потока), но значительно замедляет код (с секунд до минут)
Способ 3:
Я также попытался использовать readdirp
, он использует еще меньше памяти (~ readdirp
) и работает быстрее, но я не знаю, как его приостановить и использовать метод drain
для дальнейшего сокращения использования памяти:
const readdirp = require('readdirp')
let dir = 'C:/'
const wstream = fs.createWriteStream("C:/Users/USERNAME/Desktop/paths.txt")
readdirp(dir, {alwaysStat: false, type: 'files_directories'})
.on('data', (entry) => {
wstream.write('${entry.fullPath}\n')
})
Способ 4:
Я также попытался выполнить эту операцию с пользовательским рекурсивным обходчиком, и хотя он использует только 30 МБ памяти, что я и хотел, но он примерно в 10 раз медленнее, чем метод readdirp
и он synchronous
что нежелательно:
const fs = require('fs')
const path = require('path')
let dir = 'C:/'
function customRecursiveWalker(dir) {
fs.readdirSync(dir).forEach(file => {
let fullPath = path.join(dir, file)
// Folders
if (fs.lstatSync(fullPath).isDirectory()) {
fs.appendFileSync("C:/Users/USERNAME/Desktop/paths.txt", '${fullPath}\n')
customRecursiveWalker(fullPath)
}
// Files
else {
fs.appendFileSync("C:/Users/USERNAME/Desktop/paths.txt", '${fullPath}\n')
}
})
}
customRecursiveWalker(dir)