Каков самый быстрый способ чтения и записи крошечных, но МНОГО файлов с использованием Nodejs?

У меня есть приложение узла, которое обрабатывает файлы 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 ноября...

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
293
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Настоящим узким местом здесь будет реализация файловой системы. Запуск нескольких потоков для параллельного чтения и/или записи нескольких файлов даст вам некоторое ускорение, но вы быстро столкнетесь с узким местом файловой системы.

Как правило, типичные файловые системы плохо справляются со сценарием использования «миллионов крошечных файлов». И становится все хуже, если файлы находятся на медленных дисках, в удаленной файловой системе, в иерархической системе хранения и т. д.

Лучшее решение — перепроектировать ваше приложение, чтобы оно не организовывало свои данные таким образом. Лучшие альтернативы включают комбинации:

  • использование базы данных SQL или NOSQL для хранения данных
  • использование базы данных с плоскими файлами, такой как SQLite или BDB
  • чтение и запись архивов TAR или ZIP
  • хранение/буферизация данных в памяти.

Если вы пытаетесь повысить производительность, вам не следует искать Python. Во-первых, многопоточное приложение, привязанное к ЦП, эффективно ограничено одним ядром... из-за GIL. И ваш код Python обычно не компилируется в собственный код.

Такой язык, как C, C++ или даже Java, был бы лучшим выбором. Но распараллелить файловый ввод-вывод приложения сложно, и результаты, как правило, разочаровывают. Обычно лучше сделать это по-другому; то есть избегайте архитектур приложений, которые используют много маленьких файлов.

Поскольку эта программа находится на стороне клиента, а сгенерированные файлы используются для временных файлов до того, как программа вставит новые документы в MongoDB, кажется, я с осторожностью использовал для нее другую базу данных. Прочитав ваше решение, я понял, что SQLite может быть полезен для улучшения всей структуры моего приложения. :-)

Anteater333 25.11.2022 07:36

Или, может быть, просто собрать «файлы» JSON в памяти на стороне клиента? Но трудно дать хороший совет без более подробной информации.

Stephen C 25.11.2022 08:00

Вы пробовали 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 содержит огромное количество информации и его трудно прочитать сразу. Спасибо, но в этом случае я думаю немного иначе.

Anteater333 25.11.2022 07:51

Хорошо! В этом случае, если вы увеличите переменную среды UV_THREADPOOL_SIZE, увеличится количество внутренних пулов потоков узла, которые будут использоваться при вызовах файловой системы, таким образом, вы можете увеличить скорость работы с файлами. Ссылка: stackoverflow.com/questions/29404784/…

Davidsamuel 25.11.2022 08:15

Другие вопросы по теме