Обязан ли стандарт C ++ на низкую производительность iostreams, или я просто имею дело с плохой реализацией?

Каждый раз, когда я упоминаю низкую производительность iostreams стандартной библиотеки C ++, я встречаю волну недоверия. Тем не менее, у меня есть результаты профилировщика, показывающие большие количество времени, затрачиваемое на код библиотеки iostream (полная оптимизация компилятора), и переключение с iostreams на специфичные для ОС API ввода-вывода и настраиваемое управление буфером дает улучшение на порядок.

Какую дополнительную работу выполняет стандартная библиотека C ++ , требуется ли это по стандарту, и полезно ли это на практике? Или некоторые компиляторы предоставляют реализации iostreams, которые конкурируют с ручным управлением буфером?

Benchmarks

Чтобы сдвинуть дело с мертвой точки, я написал несколько коротких программ для проверки внутренней буферизации iostreams:

Обратите внимание, что версии ostringstream и stringbuf выполняют меньше итераций, потому что они слишком медленнее.

На ideone ostringstream примерно в 3 раза медленнее, чем std: copy + back_inserter + std :: vector и примерно в 15 раз медленнее, чем memcpy в необработанный буфер. Это похоже на профилирование до и после, когда я переключил свое настоящее приложение на настраиваемую буферизацию.

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

Было бы неплохо увидеть тесты производительности в других системах и комментарии о том, что делают обычные реализации (например, gcc libc ++, Visual C ++, Intel C ++) и сколько накладных расходов предусмотрено стандартом.

Обоснование этого test

Ряд людей правильно указали, что iostreams чаще используются для форматированного вывода. Однако они также являются единственным современным API, предоставляемым стандартом C ++ для доступа к двоичным файлам. Но настоящая причина для проведения тестов производительности внутренней буферизации относится к типичному форматированному вводу-выводу: если iostreams не может поддерживать контроллер диска с необработанными данными, как они могут поддерживать его, если они также несут ответственность за форматирование?

Тестирование времени

Все это на итерацию внешнего ( k ) цикла.

На ideone (gcc-4.3.4, Пробежал все дважды, чтобы увидеть, насколько стабильными были результаты. Довольно согласованный IMO.

ПРИМЕЧАНИЕ: на моем ноутбуке, поскольку я могу сэкономить больше процессорного времени, чем позволяет ideone, я установил количество итераций на 1000 для всех методов. Это означает, что перераспределение ostringstream и вектора , которое происходит только на первом проходе, не должно иметь большого влияния на окончательные результаты.

РЕДАКТИРОВАТЬ: К сожалению, обнаружена ошибка в файле vector -with-normal-iterator, итератор не продвигался, и поэтому было слишком много попаданий в кэш. Мне было интересно, насколько vector превосходит char [] . Это не имело большого значения, vector по-прежнему быстрее, чем char [] в VC ++ 2010.

Выводы

Буферизация выходных потоков требует трех шагов каждый раз при добавлении данных:

  • Убедитесь, что входящий блок соответствует доступному пространству буфера.
  • Скопируйте входящий блок.
  • Обновите конец-из -data pointer.

Последний опубликованный мной фрагмент кода « vector простой итератор плюс проверка границ» не только делает это, но и выделяет дополнительное пространство и перемещает существующие данные, когда входящий блок не подходит. Как указал Клиффорд, буферизация в классе файлового ввода-вывода не должна этого делать, она просто очищает текущий буфер и повторно использует его. Таким образом, это должна быть верхняя граница стоимости буферизации вывода. И это именно то, что нужно для создания рабочего буфера в памяти.

Так почему же stringbuf в 2,5 раза медленнее на ideone, и как минимум в 10 раз медленнее при тестировании? В этом простом микро-тесте он не используется полиморфно, поэтому это не объясняет.

193
задан 18 revs, 3 users 79% 23 February 2012 в 12:12
поделиться