• XSS.stack #1 – первый литературный журнал от юзеров форума

Многопоточное шифрование файлов

Encommerce

(L3) cache
Пользователь
Регистрация
25.11.2022
Сообщения
235
Реакции
97
Пишу игрушечный локер на Rust
Думаю вот как лучше распараллелить шифрование файлов

На данный момент реализация следующая:

Есть общая булевая переменная "throttling"
Есть поток, который в бесконечном цикле смотрит загрузку памяти, цп и диска, в случае чего меняя состояние вышеуказанной переменной
Есть поток, который берет таргет из очереди и в случае, если "throttling=false", пушит его в threadpool, иначе цикл с таймаутом


Это работает, но есть стойкое ощущение соплей


Как бы вы решили эту задачу?
Может кто-то знает публичные репозитории с реализацией многопоточного шифрования(тулзы или сходники тех же локеров)?
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Я советую посмотреть количество дисков и ядер процессора, после чего создавать соответсвующее количество потоков, я так как системный кодер , не знаю что за Rust... Потом просто мапить файл в память, при открытии не забывая Ovelapped применить, с учетом подсчета вышеуказанных действий менять на лету как то так (выставив поток контроля за остальными потоками естественно типа WatchDog): https://bitsum.com/tools/cpu-affinity-calculator/
 
Потом просто мапить файл в память, при открытии не забывая Ovelapped применить
Это не очень хороший совет, если мапить больше файлы, по 30-40 гб, они во-первых в оперативную память не поместятся целиком, во-вторых, если включен файл подкачки, будет затрачиваться дополнительное время на сброс непоместившейся в реальную физическую оперативную память виртуальной памяти процесса на диск. Большие файлы лучше читать последовательно, по частям, при этом вовсе не обязательно шифровать весь огромный файл целиком, достаточно распределить по этому файлу "полосы" равномерно, и шифровать только в пределах этих полос "зеброй". Скорость шифрования с таким способом взлетает очень сильно на больших файлах. Маленькие конечно же можно шифровать целиком.

Пишу игрушечный локер на Rust
Думаю вот как лучше распараллелить шифрование файлов
Общий алгоритм такой
N = <количество ядер процессора>
1) Создается пул потоков, количество потоков равное 2 * N, при этом пул нужно настроить так, что бы работали только N потоков одновременно, остальные спят, нужно это для того что бы во время переключения очереди потоков в пуле, не было простоев, некоторые потоки могут завершать работу, но пул не будет успевать выдать ему сразу новую задачу, поэтому он возьмет тот поток, который уже давно ожидает задачу (читаем про IOCP на msdn)
2) Создается глобальная очередь файлов, основной поток делает обход файлов в директориях, и закидывает файлы в очередь, так же следит за тем, что бы очередь не переполнялась, а она обязательно будет переполняться, так как операции чтения\шифрования\записи выполняются гораздо дольше, чем обход директорий, даже с учетом того, что обход работает в одном потоке, а рабочих потоков обрабатывающих файлы N штук
3) Рабочий пул потоков забирает файлы из очереди, каждый поток читает файл, шифрует его, записывает обратно, таким образом у тебя есть непрерывная поставка файлов в очередь, которую разбирают рабочие потоки и работают с файлами.

Все это делается на асинхронных вариантах работы с файлами, что бы не было задержек и простоев, для высоконагруженного софта важен каждый тик процессора, пока идет операция чтения\записи, можно пошфифровать уже считанный буфер и тд. Так же немного ускорения можно получить, если файлы открывать с отключенной буферизацией, тогда операции чтения\записи будут проходить быстрее, из-за отсутствия заполнения временных буферов выравнивания в драйверах файловой системы, но тут важно самостоятельно выравнивать буфер по границе сектора диска (физического сектора, многие путают с логическим, это разные вещи), иначе ничего не прочитается\не запишется.
 
У тебя узкое место не нагрузка на проц, а скорость записи на диск.
Скорее всего и в цпу можно упереться, при определенных конфигурациях
Например если стоит уебищный селерон с быстрым ссд или даже двумя ссд
 
RtlSetThreadAffinityMask + два порта IOCP, для Read и Write, т.е. 2 очереди вместо одной.
Начинай критиковать... :cool:
Два порта незачем создавать, так как скорость распределения задач и так очень высокая, на уровне ядра ос, там драйвер этим занимается, от двух очередей толку 0
Поясню почему одной очереди достаточно
Первое - у тебя в пределах одного файла пайплайн такой 1)считать файл, либо его часть, 2) зашифровать, 3) записать. Это все в пределах одного файла выполняется последовательно, ты не можешь сделать запись раньше, чем считал, не можешь сделать запись раньше, чем зашифровал. И не можешь зашифровать раньше чем считал. Тут распараллелить ничего не получится, в любом случае действия последовательны глобально. Паралелить обработку разных файлов - да, но в пределах одного - нет. Поэтому вторая очередь IOCP (запись после шифрования) будет просто ждать первую (чтение). Понятно что они асинхронно работают, но читай пункт ниже, и поймешь мой посыл.
Второе - скорость получения задач из очереди гораздо выше, чем сами операции чтения\записи, поэтому даже с одним портом IOCP он проставивает большую часть времени (реально процентов 80-90 времени просто ждет), ожидая пока поток какой-то освободится. Смысла во втором порте нет, он будет так же висеть ждать потоки и сьедать немного ресурсов. Так что это минус с производительность.

А вот с маской ядер нормальная тема, но там тоже нужно с умом делать, что бы отдельные потоки сильно не висли на больших файлах, имеет смысл большие файлы подразделять на подзадачи, и раздавать один и тот же файл по кускам\смещениям разным потокам. Но это достаточно сомнительная тема. Потому что если вдаваться в механическое устройство ЖД, то выгоднее читать последовательно большой файл, а если задачу чтения разбить между потоками, то они в разном порядке могут начать его читать, и головка диска будет бегать туда сюда, теряя время. Так что тут две стороны медали. Все таки я думаю, что лучше одному потоку софтверно подвиснут на одном большом файле, чем головке диска физически туда-сюда мотаться по этому же самому файлу, пока куча потоков его читает. Суммарно несколько потоков в таком случае прочитают его даже чуть медленней, если учитывать какие-то микросекунды затрачиваемые на переключение контекста + беготню головки по диску в результате этих самых перключений контекста, их порядок не предугадаешь, это как система захочет, тому потоку и даст "добро".
 
Последнее редактирование:
Скорее всего и в цпу можно упереться, при определенных конфигурациях
Например если стоит уебищный селерон с быстрым ссд или даже двумя ссд
Тестил или пишешь просто чтобы что-то написать?
 
Два порта незачем создавать, так как скорость распределения задач и так очень высокая, на уровне ядра ос, там драйвер этим занимается, от двух очередей толку 0
что бы очередь не переполнялась, а она обязательно будет переполняться
Один порт, там все операции чтения и записи. А так в одном порте запись в другом чтение.
Порты независимые друг от друга. Я делал, работает норм, производительность не проседает :cool:
Есть от маздая бородатый сорс unbufcp2 быстрого копирования файла.
Они используют 2 порта для этого.
А могли бы использовать один.
Глупые наверное! ;)
P.S. Спорить бесполезно, ты однозначно умнее... :cool:
 

Вложения

  • UnBufCp2.zip
    5.9 КБ · Просмотры: 22
Ты все больше напоминаешь мне шептуна виспера
С каждым сообщением убеждаюсь, что ты точно так же видишь только свое мнение и считаешь его единственным верным


Один порт, там все операции чтения и записи. А так в одном порте запись в другом чтение.
Порты независимые друг от друга. Я делал, работает норм, производительность не проседает :cool:
Я тебе сказал, что разницы не будет. Что один порт, что два, 90 процентов времени висят и ждут освобождения потоков, что бы дать им задачу. Просадка будет на двух портах, но в микросекундах, ты этого даже не заметишь, потому что она только теоретическая, если брать как говорят "коня в сферическом вакууме", на практике тесты у тебя то один, то другой будут давать более быстрые результаты, и в среднем будет одинаково.
Поэтому нет смысла городить 2 порта, усложняешь сам себе жизнь. Просто лишние строки кода и лишняя логика.


Есть от маздая бородатый сорс unbufcp2 быстрого копирования файла.
Они используют 2 порта для этого.
А могли бы использовать один.
Глупые наверное! ;)
P.S. Спорить бесполезно, ты однозначно умнее... :cool:
Тут играет роль тупо эстетика, и то что сорец показательный, что бы новичкам было понятнее, что там происходит, это стиль майков, все намного проще, чем ты думал, на практике разницы нет.
Ты приводишь аргументы, которые только тебе выгодны, и совсем забываешь, что у яблочка то две стороны))), ты мыслишь необьективно, и пытаешься мне зачем-то доказать, что ты прав, а я нет. В то же время я не говорю, что ты не прав, я говорю, что так сделать можно, это не ошибка, но нахера, если разницы нет ? У тебя спор ради спора. Меняй мышление.
Возьми сорцы работы с IOCP от Рихтера и ты увидишь там один порт IOCP для быстрого копирования файла, хочешь сказать Рихтер был дурачком ? Ну-ну...

Поэтому...
Спорить бесполезно, ты однозначно умнее... :cool:
 
Последнее редактирование:
Ты все больше напоминаешь мне шептуна виспера
С одной разницей, я свои слова, иногда подкрепляю исходниками.
Не заметил? Чего и тебе желаю.
ты мыслишь необьективно
Я ранее, про объективное и субъективное писал в другом треде. Не путай. Я и ты мыслим изначально субъективно. Но это так, лирика. ;)
свое мнение и считаешь его единственным верным
Это не так, не я постоянно с пеной у рта пытаюсь спорить по любому, даже незначительному поводу.
Если я не прав, я соглашаюсь и признаю это. В отличии от тебя. Перечитай свои же посты.
Вот как раз именно ты, мне "напоминаешь мне шептуна виспера".
Тот тоже много писал, но не строчки кода, своего или чужого не привел, ни разу.
Меняй мышление.
 
"где твой код ?" - встречный вопрос.. где твой код? п@здеть не мешки ворочать.. я чужой код хоть привожу в пример, от тебя вообще ноль.
Даже если ты загуглишь прмиеры работы с IOCP, хоть с файлами, хоть с сокетами, хоть с чем угодно, 9/10 результатов тебе дадут использование 1 порта, остальное - экзотика, и нет же тебе нужно было доказать свою правоту, выдрать где-то пример с двумя портами, лишь бы доказать мне что-то. Тебе интересен был не сам обьект спора, а доказательство твоей правоты, у тебя оргазмы что ли от этого, хрен знает, но выглядит нездорово это.

Твоих "других" кодеров кто-то проверял самих на дебелизм? Кроме оскорблений, ни одного вменяемого аргумента.
Давай скатимся до уровня твоих "кодеров", и начнем друг друга обзывать.
Если ты разделяешь то, что какой-то критин написал, значит ты такой же.
Я бы не бросался такими фразами, это написал очень уважаемый на этом форуме человек с большой положительной репутацией среди старожил форума, возможно он позволил себе такое высказывание в личной переписке, не на публике, и не написал бы тут тебе такого в теме просто из вежливости, но тем не менее это факт, ты несешь бред, и не один я это заметил. Кстати пишут про тебя подобное уже не первый раз. Стоит тебе ларри задуматься об этом, ой как стоит...
 
Последнее редактирование:
Пожалуйста, обратите внимание, что пользователь заблокирован
Пожалуйста, обратите внимание, что пользователь заблокирован

Регистр данных - в любом случае один и контроль прерываний тоже.
На счет маппинга - да само собой нужно смотреть размер свободной ОЗУ иначе своп - файл будет тратить время.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Мда... засрали тему челу, а в итоге ничего конструктивного.
Да прерывание контроллера юзается одно, буфер фактически тоже один на каждый диск, кроме рэйд массивов.
Реально Инде бы пояснил, чето пропал.
 
Мда... засрали тему челу, а в итоге ничего конструктивного.
Да прерывание контроллера юзается одно, буфер фактически тоже один на каждый диск, кроме рэйд массивов.
Реально Инде бы пояснил, чето пропал.
Тут загвоздка не в количестве допустимых операций, а в пропускной способности диска (чтение запись)
Одновременно не будет читаться\записываться больше чем <количество ядер процессора> файлов, потому что это указывается когда ты создаешь порт IOCP, там правильно нужно указать количество потоков равное <количество ядер процессора>
А это уже исключает перегрузку по количеству операций запущенных одновременно асинхронно
Если бы у нас было неограниченное количество потоков и все они одновременно читали и писали, тогда можно было бы упереться в IOPS, а так нет, не получится
Ну или может я не так че понял
 
Последнее редактирование:
Пожалуйста, обратите внимание, что пользователь заблокирован
Дело в контрллере(ах) дисков
Таким образом, если ОЗУ соответствует размеру блока или файла - прирост в скорости оч. большой при маппинге в том числе, можно задействовать аппаратный AES и тогда все мгновенно, а если учесть что обычно локеры юзают на серверах, где ОЗУ девать некуда + RAID постоянно, то....
тем более маппинг идет от
Код:
__kernel_entry NTSYSCALLAPI NTSTATUS NtCreateSection(
  [out]          PHANDLE            SectionHandle,
  [in]           ACCESS_MASK        DesiredAccess,
  [in, optional] POBJECT_ATTRIBUTES ObjectAttributes,
  [in, optional] PLARGE_INTEGER     MaximumSize,
  [in]           ULONG              SectionPageProtection,
  [in]           ULONG              AllocationAttributes,
  [in, optional] HANDLE             FileHandle
);
где сразу маппить всё не обязательно
 
Последнее редактирование:
просто заюзать NtCreateSection из ntdll
Насколько правдиво пишет MSDN, в прототипах нет ничего, что могло бы юзаться асинхронно с IOCP
1670347933902.png

1670347953030.png

Поэтому не получится работать асинхронно с портами IOCP, так же как это позволяют стандартные апишки для работы с файлами
Не зря же все локеры используют просто NtCreateFile + NtReadFile\NtWriteFile или их высокоуровневые аналоги
Чего-то я не вижу в параметрах ZwMapViewOfFile чего-то отдаленно напоминающего структурку OVERLAPPED
Работа с секциями не предусматривает асинхрон
 
Последнее редактирование:
Пожалуйста, обратите внимание, что пользователь заблокирован
NtCreateIoCompletion
NtCreateEvent,
1. включите фантазию используя доки, приложеные мной в виде файла ниже
2. не хочется вступать в полемику, имхо Вы оба мало изучали доки и не смотрели в дизассемблерах и отладчиках, куда ведут OVERLAPPED (IOPS, как Вы их называете функции).
 

Вложения

  • ntundoc.zip
    228 КБ · Просмотры: 20


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх