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