Производительность Mutlitask при одновременной записи файлов с отображенной памятью в Windows - PullRequest
0 голосов
/ 06 апреля 2019

На жестком диске есть несколько больших двоичных файлов (обычно по 16–32 МБ каждый), которые должны произвольно считываться и записываться несколькими потоками (конечно, внутри одного и того же процесса).

Я следовал традиционному способу: дескриптор файла из используемых файлов, затем создавал отображенные в память файлы из этих физических файлов, используя CreateFileMapping(), соответственно создавая представления в 1 МБ, используя MapViewOfFile(), чтобы произвольно читать и записывать эти блоки памяти (вид).

Суть в том, что эти представления по 1 МБ каждый четко разделены на меньшие зоны между потоками, поэтому гарантируется, что два разных потока никогда не перезаписывают одну и ту же часть. Но - ради оптимизации - я также реализовал «ручной» механизм кэширования, то есть менее используемые представления всегда дают место для часто используемых или недавно использованных для сохранения оперативной памяти.

Производительность и низкое потребление памяти являются обязательными, имеют до сотен тысяч (если не миллионов) выборок в секунду. То есть использование обычных средств синхронизации Windows (мьютексов, критических секций и т. Д.) В любых, но действительно важных местах исключено.

Теоретически я не должен слишком беспокоиться о безопасности потоков, поскольку сами зоны памяти четко разделены. Но у меня все еще могут быть проблемы, когда механизм кэширования сопоставляет / отображает определенные блоки, создаются и отображаются новые файлы и т. Д. Поэтому мне нужно сделать выбор между двумя подходами, как реализовать это:

  1. Каждый поток использует полностью разделенные дескрипторы файлов и карт, даже те же файлы будут просматриваться через разные файловые дескрипторы каждым из этих потоков.
  2. Потоки используют один и тот же (общий) дескриптор для определенного файла (здесь может потребоваться некоторая синхронизация), но каждый поток использует свою собственную MMF, созданную из этого общего дескриптора.
  3. Протекторы совместно используют даже MMF (дополнительная синхронизация здесь!), Но каждый поток использует свои собственные представления, даже если эти представления физически указывают на одну и ту же зону ОЗУ.
  4. Потоки совместно используют даже представления, поэтому потоки уже нуждаются в синхронизации, когда механизм кэширования отображает новые представления и отображает те, которые используются реже.

Ну, подход 1 будет проще всего реализовать (абсолютно не нужно никакой синхронизации), но это также может быть основным недостатком: не уверен, но у меня такое ощущение, что это просто бросок мертвого кота через забор - как в этом случае Windows будет выполнять все трудоемкие синхронизации, от которых я только что избавился.

Напротив, 4 нужен действительно сложный код и интенсивное использование критических разделов и т. Д., Поэтому я бы исключил его в начале.

Итак, по вашему мнению, какой из этих четырех подходов является оптимальным для обеспечения абсолютно поточно-безопасной работы, но в то же время оптимальная производительность и минимальные объемы ОЗУ (например, должны отображаться те же части файла) физически в одну зону ОЗУ, независимо от разных потоков и дескрипторов). Очевидно, что любые лучшие предложения также приветствуются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...