Пользование крупными библиотеками по сути делает более медленный код?

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

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

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

Напыщенная речь Torvalds (спорный, хотя это) точно не помещает мою основу непринужденно также.

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

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

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

Выведите меня из моего страдания!

46
задан Gavin 11 February 2010 в 20:23
поделиться

17 ответов

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

В вообще нет.

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

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

Честно говоря, вы беспокоитесь не о том.

30
ответ дан 26 November 2019 в 20:23
поделиться

FFTW и ATLAS - две довольно большие библиотеки. Как ни странно, они играют большую роль в самом быстром программном обеспечении в мире, приложениях, оптимизированных для работы на суперкомпьютерах. Нет, использование больших библиотек не замедляет ваш код, особенно когда альтернативой является реализация подпрограмм FFT или BLAS для себя.

0
ответ дан 26 November 2019 в 20:23
поделиться

Вы совершенно правы, когда беспокоитесь, особенно когда дело касается повышения. Это не столько из-за того, что кто-то пишет их некомпетентно, сколько из-за двух проблем.

  1. Шаблоны - это просто раздутый код. 10 лет назад это не имело большого значения, но в настоящее время ЦП работает намного быстрее, чем доступ к памяти, и эта тенденция сохраняется. Я бы почти сказал, что шаблоны - это устаревшая функция.

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

Простое добавление в iostream добавляет к вашему коду около 3 МБ (!!!). Теперь добавьте немного бреда, и у вас будет 30 МБ кода, если вы просто объявите пару особенно странных структур данных.

Хуже того, вы даже не можете легко это профилировать. Я могу сказать вам, что разница между кодом, написанным мной, и кодом из библиотек шаблонов ДРАМАТИЧЕСКАЯ, но для более наивного подхода вы можете подумать, что у вас хуже от простого теста, но затраты на раздувание кода потребуют своего инструмента в большом реальном мире приложение.

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

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

-11
ответ дан 26 November 2019 в 20:23
поделиться

fwiw, я работаю в Microsoft Windows и когда мы создаем Windows; сборки, скомпилированные для SIZE , быстрее, чем сборки, скомпилированные для SPEED , потому что вы получаете меньше обращений к страницам.

0
ответ дан 26 November 2019 в 20:23
поделиться

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

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

0
ответ дан 26 November 2019 в 20:23
поделиться

Технически ответ таков: да, это так. Однако эти неэффективности очень редко имеют практическое значение. Я собираюсь предположить здесь статически скомпилированный язык, такой как C, C ++ или D.

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

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

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

1
ответ дан 26 November 2019 в 20:23
поделиться

«Еще один мяч и цепь». Правда?

Или это стабильная и надежная платформа, которая в первую очередь позволяет вашему приложению?

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

В самом деле, они могут отказаться вмешиваться в ваше программное обеспечение именно потому, что вы избегали использования очевидной «слишком большой и ... раздутой» библиотеки.

1
ответ дан 26 November 2019 в 20:23
поделиться

К сожалению, я полагаю, что вам потребуется создать таблицу поиска для кодов языков. Это коды ISO 639-1 . Дополнительные сведения см. в разделе «Обозначения языков и языков» руководства по программированию интернационализации.

-121--4088951-

Может быть создан каталог интеграционных тестов в src/test ? Конечно, для интеграционных тестов разделение становится менее ясным, но есть что-то, что группирует A, B и C вместе, нет? Я бы начал с этого и посмотрел, как идут дела. Трудно сразу найти идеальное решение, и решение «OK» лучше, чем не решение.

-121--2733312-

Зависит от работы компоновщика. Некоторые линкеры ленивы и будут включать весь код в библиотеку. Более эффективные средства связывания извлекают из библиотеки только необходимый код. У меня был опыт с обоими типами.

Меньшие библиотеки будут меньше беспокоиться о компоновщиках любого типа. Худший случай с небольшой библиотекой - небольшие объемы неиспользуемого кода. Многие небольшие библиотеки могут увеличить время сборки. Компромисс будет строить время против кодового пространства.

Интересным тестом компоновщика является классическая программа Hello World :

#include <stdio>
#include <stdlib>
int main(void)
{
  printf("Hello World\n");
  return EXIT_SUCCESS;
}

Функция printf имеет много зависимостей из-за всего форматирования, в котором она может нуждаться. Ленивый, но быстрый компоновщик может включать в себя «стандартную библиотеку» для разрешения всех символов. Более эффективная библиотека будет включать только printf и его зависимости. Это делает линкер медленнее.

Приведенную выше программу можно сравнить с ней с помощью puts :

#include <stdio>
#include <stdlib>
int main(void)
{
  puts("Hello World\n");
  return EXIT_SUCCESS;
}

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

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

2
ответ дан 26 November 2019 в 20:23
поделиться
  1. Обычно проблемы с производительностью не развлекают их, потому что это значит угадывать , что они представляют собой проблему, потому что если вы не знаете , что это так, вы предполагаете, а угадывание является центральной концепцией «преждевременной оптимизации». Проблема с производительностью заключается в том, чтобы диагностировать их, когда они у вас , а не раньше . Вы почти никогда не догадались о проблемах. Вот расширенный пример.

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

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

2
ответ дан 26 November 2019 в 20:23
поделиться

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

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

5
ответ дан 26 November 2019 в 20:23
поделиться

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

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

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

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

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

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

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

11
ответ дан 26 November 2019 в 20:23
поделиться

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

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

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

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

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

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

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

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

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

4
ответ дан 26 November 2019 в 20:23
поделиться

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

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

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

3
ответ дан 26 November 2019 в 20:23
поделиться

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

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

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

3
ответ дан 26 November 2019 в 20:23
поделиться

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

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

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

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

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

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

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

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

13
ответ дан 26 November 2019 в 20:23
поделиться

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

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

25
ответ дан 26 November 2019 в 20:23
поделиться

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

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

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

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

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

3
ответ дан 26 November 2019 в 20:23
поделиться