Является ли std::ifstream значительно медленнее, чем FILE?

StackOverflow https://stackoverflow.com/questions/477225

Вопрос

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

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

Обновить:

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

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top