Делает ли использование больших библиотек по своей сути более медленным кодом? - PullRequest
46 голосов
/ 11 февраля 2010

У меня есть психологический тик, из-за которого я не хочу использовать большие библиотеки (например, GLib или Boost ) на языках более низкого уровня, таких как C и C ++. На мой взгляд, я думаю:

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

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

The Торвальдс декламация (спорно, хотя оно и есть) точно не поместить мое сердце в покое либо.

Есть ли основания для моего мышления, или я просто неразумный и / или невежественный? Даже если я использую только одну или две функции большой библиотеки, то, связавшись с этой библиотекой, я понесу издержки производительности во время выполнения?

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

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

Пожалуйста, избавь меня от страданий!

Ответы [ 17 ]

30 голосов
/ 11 февраля 2010

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

В общем, нет.

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

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

Честно говоря, вы беспокоитесь о неправильных вещах.

25 голосов
/ 11 февраля 2010

Я не могу комментировать GLib, но имейте в виду, что большая часть кода в Boost предназначена только для заголовков и, учитывая принцип C ++, согласно которому пользователь платит только за то, что он использует, библиотеки довольно эффективны. Есть несколько библиотек, которые требуют, чтобы вы ссылались на них (regex, файловая система), но это отдельные библиотеки. С Boost вы не связываетесь с большой монолитной библиотекой, а только с более мелкими компонентами, которые вы используете.

Конечно, другой вопрос - какая альтернатива? Вы хотите реализовать функциональность Boost самостоятельно, когда вам это нужно? Учитывая, что над этим кодом работало много очень компетентных людей и он работал на множестве компиляторов и все еще эффективен, это может быть не совсем простым делом. Кроме того, вы изобретаете велосипед, по крайней мере, в определенной степени. ИМХО, вы можете потратить это время более продуктивно.

13 голосов
/ 12 февраля 2010

Boost - не большая библиотека.

Это коллекция множества маленьких библиотек. Большинство из них настолько малы, что содержатся в заголовке или двух. Использование boost::noncopyable не перетаскивает boost::regex или boost::thread в ваш код. Это разные библиотеки. Они просто распространяются как часть одной коллекции библиотек. Но вы платите только за те, которые используете.

Но в целом, потому что большие библиотеки существуют, даже если Boost не является одним из них:

Есть ли основания для моего мышления, или я просто неразумный и / или невежественный? Даже если я использую только одну или две функции большой библиотеки, то, связавшись с этой библиотекой, я понесу издержки производительности во время выполнения?

Без основы, более или менее . Вы можете проверить это сами.

Напишите небольшую программу на C ++ и скомпилируйте ее. Теперь добавьте к нему новую функцию, которая никогда не вызывается, но определяется. Скомпилируйте программу еще раз. Предполагая, что оптимизации включены, компоновщик удаляет их, потому что они не используются. Таким образом, стоимость включения дополнительного неиспользованного кода равна нулю.

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

Другое исключение состоит в том, что если вы динамически ссылаетесь на .dll или .so, вся библиотека должна быть распределена, и поэтому она не может быть удалена из неиспользуемого кода. Но библиотеки, которые статически компилируются в ваш исполняемый файл (либо в виде статических библиотек (.lib или .a), либо просто в виде включенных заголовочных файлов), обычно могут быть обрезаны компоновщиком, удаляя неиспользуемые символы.

11 голосов
/ 11 февраля 2010

Большая библиотека с точки зрения производительности code :

  • занимают больше памяти , если у него есть исполняемый двоичный файл (большинство частей boost не требуют исполняемых двоичных файлов, они «только для заголовков»). Хотя ОС загружает в ОЗУ только фактически используемые части библиотеки, она все равно может загружать больше, чем нужно, потому что степень детализации загружаемого файла равна размеру страницы (хотя 4 Кбайт только в моей системе).
  • требуется больше времени для загрузки динамическим компоновщиком, если, опять же, ему нужны исполняемые файлы. Каждый раз, когда ваша программа загружается, динамический компоновщик должен сопоставлять каждую функцию, которую вам нужна внешняя библиотека, с ее фактическим адресом в памяти. Это занимает некоторое время, но совсем немного (однако это имеет значение при масштабах загрузки многих программ, таких как запуск среды рабочего стола, но у вас там нет выбора).

    И да, при каждом вызове внешней функции разделяемой (динамически связанной) библиотеки

с точки зрения производительности разработчика :

  • добавить внешнюю зависимость . Вы будете в зависимости от кого-то еще . Даже если это бесплатное программное обеспечение этой библиотеки, вам потребуются дополнительные расходы для его изменения. Некоторые разработчики очень низкоуровневых программ (я говорю о ядрах ОС) ненавидят полагаться на кого-либо - это их профессиональное преимущество. Таким образом, рантс.

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

  • Большие библиотеки обычно содержат специфичные для библиотеки понятия , для понимания которых требуется время. Рассмотрим Qt. Он содержит сигналы и слоты и moc связанную инфраструктуру. По сравнению с размером всего Qt их изучение занимает небольшую долю времени. Но если вы используете небольшую часть такой большой библиотеки, это может быть проблемой.

5 голосов
/ 11 февраля 2010

Избыток кода магическим образом не замедляет работу процессора. Все, что он делает, это сидит там, занимая немного памяти.

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

4 голосов
/ 12 февраля 2010

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

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

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

  3. Если вы не статически связываете все выбранные вами фреймворки и библиотеки, вы можете в конечном итоге обременять своих конечных пользователей проблемами управления версиями библиотек.

  4. Время компиляции влияет на производительность разработчика. Инкрементное связывание, предварительно скомпилированные заголовки, правильное управление зависимостями заголовков и т. Д. Могут помочь управлять временем компиляции, но не устраняют проблемы производительности компилятора, связанные с огромным количеством встроенного кода, который представляют некоторые технологии платформы.

  5. Для проектов, распространяемых как исходные, время компиляции влияет на конечных пользователей проекта.

  6. Многие технологии платформы имеют свои собственные требования к среде разработки. Эти требования могут накапливаться, что затрудняет и отнимает у новых разработчиков проекта возможность репликации среды, необходимой для компиляции и отладки.

  7. Использование некоторых действующих платформенных технологий создает новый язык программирования для проекта. Это затрудняет участие новых разработчиков.

У всех проектов есть технологические зависимости платформы, но для многих проектов есть реальные преимущества в том, чтобы свести эти зависимости к минимуму.

3 голосов
/ 12 февраля 2010

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

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

Реальный ответ для конкретной библиотеки обычно зависит от ее общей структуры. Легко думать о «Повышении» как о чем-то огромном. На самом деле это огромная коллекция библиотек, большинство из которых по отдельности довольно маленькие. Вы не можете сказать много (многозначительно) о Boost в целом, потому что отдельные библиотеки написаны разными людьми, с разными техниками, целями и т. Д. Некоторые из них (например, Format, Assign) действительно медленнее, чем что-либо еще. Вы, скорее всего, будете делать это самостоятельно. Другие (например, пул) предоставляют вещи, которые вы можете сделать сами, но, вероятно, не сделаете, чтобы получить хотя бы небольшие улучшения скорости Некоторые (например, uBlas) используют сверхмощную магию шаблонов, чтобы работать быстрее, чем кто-либо, но лишь небольшой процент из нас может надеяться достичь самостоятельно.

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

Некоторые библиотеки также отводят много места, кода (и часто, по крайней мере, биты времени) для решения проблем, о которых вы, возможно, совершенно не заботитесь. Например, несколько лет назад я использовал библиотеку обработки изображений. Его поддержка более 200 форматов изображений звучала действительно впечатляюще (и в некотором смысле так и было), но я уверен, что никогда не использовал его для работы с более чем дюжиной форматов (и я, вероятно, мог бы получить, поддерживая только половину много). OTOH, даже при том, что это было все еще довольно быстро. Поддержка меньшего количества рынков могла бы ограничить их рынок до такой степени, что код на самом деле был бы медленнее (например, он обрабатывал JPEG быстрее, чем IJG).

3 голосов
/ 11 февраля 2010

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

Однако не будет никаких накладных расходов, когда все будет загружено.

Если вы не хотите использовать все повышения, то не используйте. Он модульный, поэтому вы можете использовать нужные вам части и игнорировать остальные.

3 голосов
/ 12 февраля 2010

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

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

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

2 голосов
/ 12 февраля 2010
  1. В общем, проблемы с производительностью не связаны с развлечением, потому что для этого нужно угадать , что они представляют собой проблему, потому что если вы не't знаю они, как вы догадываетесь, и угадывание является центральной концепцией "преждевременной оптимизации".Проблема, связанная с производительностью, заключается в том, что, когда они у вас есть, , а не раньше , диагностируйте их.Проблемы почти никогда не бывают тем, о чем вы могли бы догадаться. Вот расширенный пример.

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

В то же время, я делюсь вашей осторожностью в отношении сторонних библиотек и тому подобного.Слишком много раз я работал над проектами, в которых какой-то сторонний пакет «использовался» для «синергии», а затем поставщик либо просто задыхался, либо отказывался от продукта, либо он устарел, потому что Microsoft изменила что-то в ОС.Тогда наш продукт, в значительной степени опирающийся на сторонний пакет, перестает работать, что требует больших затрат с нашей стороны, в то время как оригинальных программистов уже давно нет.

...