LINUX.ORG.RU

История изменений

Исправление iliyap, (текущая версия) :

У меня microSD карта Samsung Evo+ 64 GB (UHS Class 1). При подключении через USB 3 ридер тесты последовательного чтения (dd if=/dev/sdc iflag=direct) показывают вот такие числа:

  • bs=4K: 11 MB/s
  • bs=16K: 30 MB/s
  • bs=64K: 80 MB/s
  • bs=1M: 90 MB/s

При подключении через PCIe ридер тесты последовательного чтения (dd if=/dev/mmcblk0 iflag=direct) показывают вот такие числа:

  • bs=4K: 5 MB/s
  • bs=16K: 17 MB/s
  • bs=64K: 40 MB/s
  • bs=1M: 77 MB/s

Значит прочитать последовательно 512 GB это 97 минут в лучшем случае. Согласно https://www.sdcard.org/developers/sd-standard-overview/speed-class/ пропускная способность 90 MB/s это максимум, на который способен интерфейс SD.

Кажется твоя проблема в том, что метаданные перемешаны с данными, и для чтения метаданных приходится читать все данные. Хотя метаданных там 32/15K, то есть ~1/500 (около 0.2%).

Если бы твоя карта была разбита на 2 раздела (500 GB данные + 1 GB метаданные), и каждый раздел писался бы по кругу, то для чтения метаданных надо было бы прочитать всего 1 GB (менее 15 секунд).

Касательно fread. Во-первых FILE* не умеет в O_DIRECT. Соответственно есть буферизация в ядерный page cache, есть буферизация в setvbuf buffer. Есть ещё твой буфер, который ты передаёшь в fread(). Если он «20 байт» то им можно принебречь. Если же он сопоставим по размеру с setvbuf buffer, то это тройная буферизация. Использование open(O_DIRECT) позволяет исключить page cache. Использование read() позволяет исключить setvbuf buffer.

Касательно mmap. Он позволяет отмапить в адресное пространство процесса ядерный page cache. Но mmap не даёт возможности выбрать размер блока для чтения. Ядерный page cache будет сам читать с карты каким-то блоком. Это может оказаться маленький блок и чтение будет небыстрым.

Исходная версия iliyap, :

У меня microSD карта Samsung Evo+ 64 GB (UHS Class 1). При подключении через USB 3 ридер тесты последовательного чтения (dd if=/dev/sdc iflag=direct) показывают вот такие числа:

  • bs=4K: 11 MB/s
  • bs=16K: 30 MB/s
  • bs=64K: 80 MB/s
  • bs=1M: 90 MB/s

При подключении через PCIe ридер тесты последовательного чтения (dd if=/dev/mmcblk0 iflag=direct) показывают вот такие числа:

  • bs=4K: 5 MB/s
  • bs=16K: 17 MB/s
  • bs=64K: 40 MB/s
  • bs=1M: 77 MB/s

Значит прочитать последовательно 512 GB это 97 минут в лучшем случае.

Кажется твоя проблема в том, что метаданные перемешаны с данными, и для чтения метаданных приходится читать все данные. Хотя метаданных там 32/15K, то есть ~1/500 (около 0.2%).

Если бы твоя карта была разбита на 2 раздела (500 GB данные + 1 GB метаданные), и каждый раздел писался бы по кругу, то для чтения метаданных надо было бы прочитать всего 1 GB (менее 15 секунд).

Касательно fread. Во-первых FILE* не умеет в O_DIRECT. Соответственно есть буферизация в ядерный page cache, есть буферизация в setvbuf buffer. Есть ещё твой буфер, который ты передаёшь в fread(). Если он «20 байт» то им можно принебречь. Если же он сопоставим по размеру с setvbuf buffer, то это тройная буферизация. Использование open(O_DIRECT) позволяет исключить page cache. Использование read() позволяет исключить setvbuf buffer.

Касательно mmap. Он позволяет отмапить в адресное пространство процесса ядерный page cache. Но mmap не даёт возможности выбрать размер блока для чтения. Ядерный page cache будет сам читать с карты каким-то блоком. Это может оказаться маленький блок и чтение будет небыстрым.