Запись небольших данных против больших данных на SSD.

Вопрос или проблема

Я создаю программу для перемещения разделов для развлечения. Она находит раздел, считывая схему разделов, такую как GPT или MBR, затем считывает сектор (512B) из раздела и записывает его на новое место. Но по какой-то причине этот процесс очень медленный, этот диск поддерживает скорость до 2GB/s, однако процесс идет только на 700KB/s. Это потому что мне следует считывать/записывать более крупные объемы данных за раз, и почему? Есть ли какие-нибудь другие приемы, которые я могу использовать для ускорения?

С маленьким размером (512 байт), где нужно перемещать как минимум сотни мегабайт, вы сталкиваетесь с проблемой секторов размером 4096 байт — в реальном сценарии вы читаете 4096 байт исходных данных, затем читаете данные целевого сектора (4096 B), добавляете ваши 512 байт к этому и записываете снова 4096 байт. У SSD дисков секторы по 4096, поэтому, когда вы перемещаете только 512 байт, диску нужно будет читать 4096 байт. Это так и задумывалось.

Также, при перемещении мегабайт данных, вы должны учитывать, перемещаете ли вы данные вперед или назад. Если назад — вы не должны перезаписывать следующие данные, которые будут перемещены. Если вперед — тут проблем нет. Это решается в инструкции memcpy для ассемблера, которая, если целевые данные находятся раньше в RAM (здесь на диске), перемещает данные с конца, а не с начала.

Так что ваше решение — перемещать намного больше данных, я предлагаю 100 МБ за раз. Перестаньте перемещать столько данных, когда дойдете до конца раздела, перемещайте только часть тогда. И наконец, если вы перемещаете данные назад, вы должны перемещать их с конца, а не с начала. Только если вы перезаписываете то же пространство, из которого читали.

При перемещении 512 байт вы теряете много времени на две вещи:

  1. доступ к нужным секторам на диске (наносекунды, но множество операций дают низкую производительность)
  2. чтение данных из-за размера секторов (вы перемещаете 512 байт, но диск должен читать и записывать 4096 байт)

Скорее всего, основная часть вашего времени уходит на выполнение запросов чтения/записи, а не на само чтение/запись.

Если мои расчеты верны, то 2 ГБ/с переводятся в примерно 0,3 мкс для чтения 512 байт, но всегда есть ненулевой лаг для каждого запроса, который, по моему мнению, составляет около 100 мкс? — так что если вы читаете один мегабайт с помощью отдельных запросов по 512 байт (0,3×2048 + 100×2048), то 99,997% вашего общего времени “тратится” на выполнение запросов.

Между тем, если вы делаете один запрос на чтение 1 мегабайта (0,3×2048 + 100×1), то затраты на выполнение запроса составляют всего 14%, а для чтения 128 МБ это всего 0,1%. [Это очень приблизительные цифры.]

(Для жестких дисков это будет аналогично медленно — современный SATA HDD может читать или записывать ~200 МБ/с, если он читает непрерывный блок, но если вы заставите его переходить от ‘места чтения’ к ‘месту записи’ каждый раз, то легко 90% от общего времени будет тратиться на перемещение головок, а не на само чтение/запись.)

Так что “трюк” заключается в том, чтобы делать более крупные запросы и меньшее их количество.

.

Ответ или решение

Теория

При работе с данными на SSD (твердотельных накопителях) важно учитывать несколько технических аспектов, которые напрямую влияют на производительность. SSD диски значительно отличаются от традиционных жестких дисков (HDD) из-за своей архитектуры и принципа работы. Одним из ключевых факторов, определяющих быстрое чтение и запись на SSD, является размер порции данных, с которыми ведется работа.

Твердотельные накопители имеют блоки ячеек, обычно размером 4096 байт (4КБ), которые необходимо читать или записывать в одно и то же время, даже если фактически данных меньше. Этот процесс называется выравниванием доступа. При операции записи или чтения меньшего количества байт, допустим 512 байт, накопитель все равно вынужден обрабатывать весь блок данных размером 4КБ. Это приводит к накладным расходам, связанным с дополнительными действиями по чтению и записи, даже если фактические данные малы.

Более того, почему запросы становятся медленными на уровне микросекундной задержки каждого ввода-вывода — каждая операция чтения/записи имеет накладные издержки, связанные с латентностью, которые намного больше самого времени передачи данных.

Пример

Рассмотрим конкретный сценарий: задача состоит в перемещении разделов жесткого диска, которые могут включать огромное количество таких операций с малыми данными (512 байт). Если скорость накопителя составляет 2ГБ/с, а каждую операцию чтения/записи сопровождают задержки порядка 100 микросекунд, тогда общий вклад этих задержек станет значительным. Если обработка 512 байт займет 0.3 микросекунды, но добавляется 100 микросекунд лишь на инициацию запроса, эффективность значительно снижается.

Применение

Как повысить эффективность:

  1. Увеличение размера блока данных:
    Самым простым и эффективным способом является увеличение размера данных, с которыми выполняется одна операция, например, до 1МБ. Это позволит значительно снизить процент времени на накладные расходы по сравнению с фактическим чтением и записью данных.

  2. Оптимизация последовательности операций:
    При перемещении больших объемов данных из одного места в другое важно учитывать направление движения данных. Перемещение данных "назад" может разрушить данные, которые будут использованы в будущем, если вести его с начала, тогда как перемещение "вперед" таких проблем не создает.

  3. Алгоритмическая оптимизация:
    Реализуйте стратегии, как в memcpy на ассемблере, которые учитывают относительное расположение адресов источника и назначения и позволяют проводить операции с наибольшей эффективностью, избегая перезаписывания данных в неправильной очередности.

  4. Использование современных библиотек и API:
    Коммерческие библиотеки и встроенные возможности ОС могут учитывать многие из этих аспектов и оптимизировать операции с данными таким образом, чтобы вы могли напрямую работать с большими блоками.

Подводя итог, для повышения производительности операций с SSD необходимо максимально увеличивать размер блока данных, с которыми производится работа, чтобы минимизировать накладные расходы на каждую операцию чтения и записи, а также правильно организовывать последовательность перемещений данных для предотвращения потерь.

Оцените материал
Добавить комментарий

Капча загружается...