Чтение бинарных файлов, Linux Buffer Cache - PullRequest
2 голосов
/ 10 августа 2009

Я занят написанием чего-то, чтобы проверить скорость чтения дискового ввода-вывода в Linux.

На данный момент у меня есть что-то вроде этого для чтения файлов:

Отредактировано, чтобы изменить код на это:

  const int segsize = 1048576;
  char buffer[segsize];
  ifstream file;
  file.open(sFile.c_str());
  while(file.readsome(buffer,segsize)) {}

Для файла foo.dat, который составляет 150 ГБ, при первом чтении, это занимает около 2 минут. Однако, если я запустил его в течение 60 секунд после первого запуска, запуск займет около 3 секунд. Как это возможно? Конечно, единственное место, которое может быть прочитано с такой скоростью, это буферный кеш в ОЗУ, а файл слишком большой, чтобы поместиться в ОЗУ.

Машина имеет 50 ГБ оперативной памяти, а диск имеет крепление NFS со всеми настройками по умолчанию. Пожалуйста, дайте мне знать, где я могу посмотреть, чтобы убедиться, что этот файл действительно читается с такой скоростью? Мой код неверен? Похоже, что при первом чтении файла требуется определенное количество времени.

Отредактировано для добавления: Выяснил, что мои файлы только читают до случайной точки. Мне удалось это исправить, изменив размер сегмента до 1024 с 1048576. Я понятия не имею, почему изменение этого параметра позволяет ifstream читать весь файл вместо остановки в произвольной точке.

Спасибо за ответы.

Ответы [ 5 ]

4 голосов
/ 10 августа 2009

В Linux вы можете сделать это для быстрого сквозного теста:

$ dd if=/dev/md0 of=/dev/null bs=1M count=200
200+0 records in
200+0 records out
209715200 bytes (210 MB) copied, 0.863904 s, 243 MB/s

$ dd if=/dev/md0 of=/dev/null bs=1M count=200
200+0 records in
200+0 records out
209715200 bytes (210 MB) copied, 0.0748273 s, 2.8 GB/s

$ sync && echo 3 > /proc/sys/vm/drop_caches

$ dd if=/dev/md0 of=/dev/null bs=1M count=200
200+0 records in
200+0 records out
209715200 bytes (210 MB) copied, 0.919688 s, 228 MB/s

echo 3 > /proc/sys/vm/drop_caches правильно очистит кеш

3 голосов
/ 10 августа 2009
  • in_avail указывает не длину файла, а нижнюю границу того, что доступно (особенно если буфер уже используется, он возвращает размер, доступный в буфере).Его цель - узнать, что можно прочитать без блокировки.

  • unsigned int, скорее всего, не может содержать длину более 4 ГБ, поэтому то, что читается, вполне может быть в кеше.

  • C ++ 0x Позиционирование потока может быть вам интересно, если вы используете большие файлы

1 голос
/ 10 августа 2009

Одна из возможностей заключается в том, что файл может быть хотя бы частично разреженным. У разреженного файла есть области, которые действительно пусты - у них даже нет выделенного им дискового пространства. Эти разреженные области также не занимают много места в кеше, поэтому чтение разреженных областей по существу потребует только времени для обнуления страниц пользовательского пространства, в которые они читаются.

Вы можете проверить с помощью ls -lsh. Первый столбец будет иметь размер на диске - если он меньше размера файла, файл действительно разреженный. Чтобы удалить файл, просто напишите на каждую его страницу.

Если вы хотите проверить истинные скорости диска, одним из вариантов будет использование флага O_DIRECT для open (2) для обхода кэша. Обратите внимание, что все операции ввода-вывода, использующие O_DIRECT, должны быть выровнены по страницам, и некоторые файловые системы не поддерживают его (в частности, он не будет работать через NFS). Кроме того, это плохая идея для чего-либо, кроме тестирования. См. Некоторые из рантов Линуса в этой теме .

Наконец, чтобы сбросить все кэши в системе linux для тестирования, вы можете сделать:

echo 3 > /proc/sys/vm/drop_caches

Если вы сделаете это как на клиенте, так и на сервере, вы вытесните файл из памяти. Конечно, это отрицательно скажется на производительности всего, что работает в данный момент.

1 голос
/ 10 августа 2009

Похоже, что при первом чтении файла требуется определенное время.

При первом чтении вы читаете 150 ГБ примерно за 2 минуты. Это работает до 10 гигабит в секунду. Это то, что вы ожидаете (в зависимости от сети к вашему NFS-монтированию)?

1 голос
/ 10 августа 2009

in_avail возвращает нижнюю границу того, сколько доступно для чтения в буфере чтения потоков, а не размер файла. Чтобы прочитать весь файл через поток, просто продолжайте вызов метода readsome () потока и проверка количества прочитанного с помощью метода gcount () - когда он возвращает ноль, вы прочитали все.

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