У меня есть приложение узла, которое обрабатывает файлы JSON: оно читает, анализирует файлы и записывает новые файлы. А иногда, по необходимости, файлы становятся огромным роем. Во-первых, я думаю, что текущая скорость чтения выглядит разумной, но скорость записи кажется немного медленной.
Я хотел бы улучшить эту скорость обработки.
Прежде чем прикоснуться к этой программе, я сначала попробовал многопоточность в своем приложении на Python, оно выполняет аналогичные задачи, но обрабатывает файлы изображений, и многопоточность успешно сократила время отклика.
Интересно, можно ли использовать узел worker_thread
, чтобы получить тот же эффект. Поскольку в документе Node говорится
Они не очень помогают при работе с интенсивным вводом-выводом. Встроенные в Node.js асинхронные операции ввода-вывода более эффективны, чем рабочие процессы.
https://nodejs.org/api/worker_threads.html
Проблема в том, что я не знаю, является ли текущая скорость самой быстрой, которую может показать среда узла, или ее можно улучшить без worker_thread
.
Вот мои попытки для важности: Моя программа читает и записывает файлы один за другим из списка путей к файлам, с функциями fs-sync
- readFileSync()
, writeFileSync()
. Во-первых, я думал, что синхронный доступ ко многим файлам не является узловым, поэтому я промисовал fs
функции (readFile()
, writeFile()
) и помещал их в список объектов промисов. Тогда я звоню await Promise.all(promisesList)
. Но это совсем не помогло. Еще медленнее.
Со второй попытки я отказался от генерации тонов обещаний и дал одно обещание. Он продолжал следить за количеством обработанных файлов и вызывать resolve()
, когда число равно длине всех файлов.
const waiter = new Promise<boolean>((resolve, rejects) => {
const loop: () => void = () =>
processedCount === fileLen ? resolve(true) : setTimeout(loop);
loop();
});
Я только ждал этого обещания, и это было самым медленным.
Теперь я думаю, что это показывает, что «асинхронный» не означает «параллельный». Итак, я неправильно понимаю объяснение документа? И должен ли я использовать worker_threads
для повышения скорости ввода-вывода файлов в этом случае? Или есть лучшее решение? Может быть, это может быть ответом на то, чтобы не использовать Node для таких процессов, я бы с удовольствием, но, к сожалению, сегодня 25 ноября...
Настоящим узким местом здесь будет реализация файловой системы. Запуск нескольких потоков для параллельного чтения и/или записи нескольких файлов даст вам некоторое ускорение, но вы быстро столкнетесь с узким местом файловой системы.
Как правило, типичные файловые системы плохо справляются со сценарием использования «миллионов крошечных файлов». И становится все хуже, если файлы находятся на медленных дисках, в удаленной файловой системе, в иерархической системе хранения и т. д.
Лучшее решение — перепроектировать ваше приложение, чтобы оно не организовывало свои данные таким образом. Лучшие альтернативы включают комбинации:
Если вы пытаетесь повысить производительность, вам не следует искать Python. Во-первых, многопоточное приложение, привязанное к ЦП, эффективно ограничено одним ядром... из-за GIL. И ваш код Python обычно не компилируется в собственный код.
Такой язык, как C, C++ или даже Java, был бы лучшим выбором. Но распараллелить файловый ввод-вывод приложения сложно, и результаты, как правило, разочаровывают. Обычно лучше сделать это по-другому; то есть избегайте архитектур приложений, которые используют много маленьких файлов.
Или, может быть, просто собрать «файлы» JSON в памяти на стороне клиента? Но трудно дать хороший совет без более подробной информации.
Вы пробовали API потоков узлов. Также существует пакет JSONStream npm для анализа данных потока json. Пожалуйста, посмотрите.
const fs = require('fs');
let sourceFileStream = fs.createReadStream('./file1.json')
let destinationFileStream = fs.createWriteStream('./temp/file1.json')
sourceFileStream.pipe(destinationFileStream)
Я использовал пакет JSONStream для случая, когда целевой файл JSON содержит огромное количество информации и его трудно прочитать сразу. Спасибо, но в этом случае я думаю немного иначе.
Хорошо! В этом случае, если вы увеличите переменную среды UV_THREADPOOL_SIZE, увеличится количество внутренних пулов потоков узла, которые будут использоваться при вызовах файловой системы, таким образом, вы можете увеличить скорость работы с файлами. Ссылка: stackoverflow.com/questions/29404784/…
Поскольку эта программа находится на стороне клиента, а сгенерированные файлы используются для временных файлов до того, как программа вставит новые документы в MongoDB, кажется, я с осторожностью использовал для нее другую базу данных. Прочитав ваше решение, я понял, что SQLite может быть полезен для улучшения всей структуры моего приложения. :-)