Является ли std :: ifstream значительно медленнее, чем FILE? - PullRequest
12 голосов
/ 25 января 2009

Мне сообщили, что моя библиотека работает медленнее, чем должно быть, порядка 30+ раз слишком медленный анализ определенного файла (текстовый файл, размер 326 кб). Пользователь предположил, что, возможно, я использую std::ifstream (предположительно вместо FILE).

Я бы предпочел не слепо переписывать, поэтому я решил сначала проверить здесь, так как мое предположение было бы узким местом в другом месте. Я читаю символ за символом, поэтому я использую только функции get(), peek() и tellg()/seekg().

Обновление:

Я профилировал и получил сбивающий с толку вывод - gprof, похоже, не думал, что это заняло так много времени. Я переписал программу, чтобы сначала прочитать весь файл в буфер, и он ускорился примерно в 100 раз. Я думаю, что проблема могла быть в tellg()/seekg(), который занял много времени, но gprof, возможно, не смог этого понять по какой-то причине. В любом случае ifstream делает не , похоже, для буферизации всего файла, даже для этого размера.

Ответы [ 6 ]

25 голосов
/ 25 января 2009

Я не думаю, что это будет иметь значение. Особенно, если вы читаете символ за символом, накладные расходы на ввод / вывод, вероятно, будут полностью доминировать над чем-либо остальным. Почему вы читаете отдельные байты за раз? Вы знаете, как это крайне неэффективно?

Для файла размером 326 Кбайт самым быстрым решением, скорее всего, будет просто прочитать его в память сразу.

Разница между std :: ifstream и эквивалентами C, по сути, является вызовом виртуальной функции или двумя. Это может иметь значение, если выполняется несколько десятков миллионов раз в секунду, иначе не получится. Файловый ввод-вывод обычно настолько медленный, что API, используемый для доступа к нему, на самом деле не имеет значения Гораздо важнее шаблон чтения / записи. Многие поиски плохие, последовательные чтения / записи хорошие.

4 голосов
/ 25 января 2009

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

3 голосов
/ 25 января 2009

Я думаю, что вряд ли ваша проблема будет решена путем переключения с fstream на FILE *, обычно оба буферизируются библиотекой C. Также ОС может кэшировать чтения (linux очень хорош в этом аспекте). Учитывая размер файла, к которому вы обращаетесь, вполне вероятно, что он будет полностью в оперативной памяти.

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

Также вы используете seekg / tellg, это может вызвать заметные задержки, если ваш диск сильно фрагментирован, потому что для чтения файла в первый раз, диск должен переместить головки в правильное положение.

2 голосов
/ 25 января 2009

Все тесты злые. Просто профилируйте свой код для ожидаемых данных.

Я провел сравнение производительности ввода-вывода между Ruby, Python, Perl, C ++ один раз. Для моих данных, языковых версий и т. Д. Вариант C ++ был в несколько раз медленнее (в то время это был большой сюрприз).

1 голос
/ 02 февраля 2009

Я согласен, что вы должны профиль. Но если вы читаете файл символом за раз, как насчет создания файла с отображением в памяти? Таким образом, вы можете обращаться с файлом как с массивом символов, а ОС должна позаботиться обо всей низкоуровневой буферизации. Самое простое и, вероятно, самое быстрое решение - это победа в моей книге. :)

0 голосов
/ 07 марта 2015

Здесь является отличным тестом, который показывает, что в экстремальных условиях fstream с на самом деле довольно медленные ... если только:

  1. Вы используете буферизацию (я не могу этого подчеркнуть)
  2. Вы сами управляете буфером (то есть, если вам нужна производительность, такая как OP в связанном вопросе), которая ничем не отличается от использования FILE*.

Вы не должны оптимизировать преждевременно. fstreams обычно лучше, и если вам нужно оптимизировать их в дороге, вы всегда можете сделать это позже с небольшими затратами. Чтобы заранее подготовиться к худшему, я предлагаю создать минимальный прокси-сервер для fstream сейчас, чтобы вы могли оптимизировать его позже, не трогая ничего другого.

...