Как изменить размер буфера с boost :: iostreams? - PullRequest
6 голосов
/ 09 июля 2010

Моя программа читает десятки очень больших файлов параллельно, по одной строке за раз. Кажется, что основным узким местом производительности является время поиска жесткого диска от файла к файлу (хотя я не совсем уверен, как это проверить), поэтому я думаю, что было бы быстрее, если бы я мог буферизовать ввод.

Я использую такой код C ++ для чтения моих файлов через «фильтрацию потоков» boost :: iostreams:

input = new filtering_istream;
input->push(gzip_decompressor());
file_source in (fname);
input->push(in);

Согласно документации , file_source не имеет никакого способа установить размер буфера, но filtering_stream :: push кажется:

void push( const T& t,
  std::streamsize buffer_size,
  std::streamsize pback_size );

Итак, я попытался input->push(in, 1E9), и действительно, использование памяти моей программой увеличилось, но скорость не изменилась вообще.

Я был просто неправ, что буферизация чтения повысила бы производительность? Или я сделал это неправильно? Могу ли я напрямую буферизовать file_source или мне нужно создать filtering_streambuf? Если последнее, как это работает? Документация не совсем полна примеров.

1 Ответ

2 голосов
/ 09 июля 2010

Вы должны также профилировать его, чтобы увидеть узкое место.

Возможно, оно находится в ядре, возможно, на вашем аппаратном уровне.Пока вы не профилируете это, чтобы обнаружить, что вы спотыкаетесь в темноте.

РЕДАКТИРОВАТЬ:

Хорошо, тогда более подробный ответ на этот раз.Согласно документации Boost.Iostreams basic_file_source - это просто оболочка вокруг std::filebuf, которая, в свою очередь, основана на std::streambuf.Чтобы процитировать документацию:

CopyConstructible и Assignable оболочка для std :: basic_filebuf, открытого в режиме только для чтения.

streambuf действительно предоставляет метод pubsetbuf (возможно, не лучшая ссылка, но первый обнаруженный Google), который вы, очевидно, можете использовать для управления размером буфера.

Например:

#include <fstream>

int main()
{
  char buf[4096];
  std::ifstream f;
  f.rdbuf()->pubsetbuf(buf, 4096);
  f.open("/tmp/large_file", std::ios::binary);

  while( !f.eof() )
  {
      char rbuf[1024];
      f.read(rbuf, 1024);
  }

  return 0;
}

В моем тесте (хотя оптимизация отключена) я на самом деле получил худшую производительность с буфером 4096 байт, чем буфер 16 байт, но YMMV - хороший примерпочему вы всегда должны сначала указывать профиль:)

Но, как вы говорите, basic_file_sink не предоставляет никаких средств для доступа к нему, поскольку скрывает базовый filebuf в приватной части .

Если вы считаете, что это неправильно, вы можете:

  1. Призывать разработчиков Boost раскрыть такие функции, использовать список рассылки или trac.
  2. Создайте свойсобственная filebuf оболочка, которая показывает размер буфера.В учебном пособии есть раздел , который объясняет написание пользовательских источников, которые могут быть хорошей отправной точкой.
  3. Напишите пользовательский источник, основанный на чем угодно, что делает все, что вам нравится, кэшированием.

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

И в заключение слово о профилировании.Для Linux доступно множество мощных инструментов профилирования, и я даже не знаю половину из них по именам, но, например, есть iotop , который довольно удобен, потому что он очень прост в использовании.Это очень похоже на top, но показывает метрики, связанные с диском.Например:

Total DISK READ: 31.23 M/s | Total DISK WRITE: 109.36 K/s
TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND          
19502 be/4 staffan    31.23 M/s    0.00 B/s  0.00 % 91.93 % ./apa

говорит мне, что моя программа проводит более 90% своего времени в ожидании ввода-вывода, то есть она связана с вводом-выводом.Если вам нужно что-то более мощное, я уверен, что Google может помочь вам.

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

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