Статическая компоновка против динамической компоновки

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

1) Разница в производительности во время выполнения между статическим и динамическим связыванием обычно незначительна.

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


person Eloff    schedule 03.01.2010    source источник
comment
При статической компоновке компилятор может оптимизировать .. код библиотеки, но только если он компилирует и его! Если вы просто создадите ссылку на предварительно скомпилированные объектные файлы, ваш компилятор не сможет их оптимизировать.   -  person    schedule 03.01.2010
comment
Если это правда, то вы правы, но есть некоторый вопрос, насколько это верно с современными компиляторами, если кто-то может проверить это так или иначе, это было бы здорово.   -  person Eloff    schedule 03.01.2010
comment
С компилятором, компилирующим собственный код (как и большинство компиляторов C / C ++), больше нет шансов на оптимизацию кода. Если код скомпилирован на некотором промежуточном языке (например, .Net IL), JIT-компилятор вызывается, когда библиотека загружается, чтобы скомпилировать его в собственный код. Эта окончательная компиляция может со временем улучшаться по мере развития JIT-компилятора.   -  person Tarydon    schedule 03.01.2010
comment
@Eloff: VS2008 делает именно это с включенным LTCG. (Хотя файлы lib становятся огромными ...) Я поигрался с ними, и для тех, кто интересуется тем, что может сделать для меня мой компилятор, это просто потрясающе.   -  person peterchen    schedule 03.01.2010


Ответы (17)


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

Некоторые правки, чтобы включить очень важные предложения в комментарии и другие ответы. Я хотел бы отметить, что то, как вы откажетесь от этого, во многом зависит от того, в какой среде вы планируете работать. Минимальные встроенные системы могут не иметь достаточно ресурсов для поддержки динамического связывания. Немного более крупные небольшие системы могут поддерживать динамическое связывание, потому что их память достаточно мала, чтобы сделать экономию ОЗУ за счет динамического связывания очень привлекательной. Полноценные потребительские ПК, как отмечает Марк, обладают огромными ресурсами, и вы, вероятно, можете позволить проблемам с удобством управлять своими мыслями по этому поводу.


Чтобы решить проблемы с производительностью и эффективностью: это зависит.

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

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

Еще одна проблема: время загрузки. В какой-то момент вы оплачиваете погрузку. Когда вы платите, эта стоимость зависит от того, как работает ОС, а также от того, какие ссылки вы используете. Может быть, вы лучше отложите оплату, пока не узнаете, что вам это нужно.

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

На вопросы о производительности можно ответить всегда путем тестирования (и использовать тестовую среду, максимально похожую на среду развертывания).

person dmckee --- ex-moderator kitten    schedule 03.01.2010
comment
Потребление ресурсов - это в основном пространство кода, которое с течением времени вызывает все меньше и меньше беспокойства. Если 500 КБ библиотеки разделяется между 5 процессами, это экономия 2 МБ, что составляет менее 0,1% от 3 ГБ ОЗУ. - person Mark Ransom; 03.01.2010
comment
Если библиотека также использует одно и то же виртуальное сопоставление (один и тот же физический и виртуальный адрес во всех процессах), разве динамическая ссылка не сохраняет также слоты TLB в MMU процессора? - person Zan Lynx; 03.01.2010
comment
Кроме того, динамическая ссылка позволяет легко обновлять код библиотеки с ошибками лучшими версиями. - person Zan Lynx; 03.01.2010
comment
@Zan Это также упрощает добавление ошибочного кода в рабочую версию. - person ; 04.01.2010
comment
На самом деле это не касается последствий для производительности, но это может быть связано с тем, что (1) истинно, и они незначительны в большинстве случаев. Вы сделали очень хороший обзор практических последствий динамического и статического связывания в нормальных условиях. - person Eloff; 05.01.2010
comment
Другой случай, когда вам следует использовать динамическое связывание, - это скомпилированная программа со встроенным интерпретатором, который ожидает совместного использования кода с скомпилированной программой. Например, игра, написанная на C ++, но с расширениями Lua, которым необходимо загружать часть того же кода C ++ через разделяемые библиотеки. Если такое приложение статически связано и часть его кода загружается во второй раз из общей библиотеки, это может вызвать неопределенное поведение (например, в C ++ это может быть нарушением правила единого определения или ODR). Есть несколько способов обойти это, но гибридные программы имеют тенденцию динамически связываться. - person John Zwinck; 26.02.2014
comment
Преимущество статической компоновки заключается в том, что она позволяет компоновщику вырезать неиспользуемый код, поэтому использование памяти приложением может быть уменьшено. Однако вам нужно беспокоиться о версиях среды выполнения C. - person Rai; 08.07.2014
comment
@Rai: В большинстве архивов исполняемых файлов * (формат) * символы используют разные файлы внутри исполняемых файлов (символы в исполняемых файлах не используются ОС). Итак, поскольку ОС должна интерпретировать формат файла, почему она будет хранить весь файл в ОЗУ, а не просто копировать двоичный код для его запуска. До сих пор я никогда не находил символы исполняемых файлов в дампах памяти, которые я запускал ... но я ошибаюсь? - person user2284570; 29.07.2014
comment
@ user2284570: Боюсь, я не понимаю ваш комментарий, но позвольте мне прояснить свой. Предположим, у меня есть библиотека, созданная как в виде DLL, так и в виде статической библиотеки. Рассмотрим приложение, которое вызывает библиотечную функцию. Если я свяжу статически, код для библиотечных функций, которые приложение не использует, может быть проигнорирован компоновщиком, то есть использование памяти включает только код, который приложение фактически использует. Если я подключаю динамически, вся DLL загружается в память, поэтому использование памяти может быть больше (задержка загрузки может измениться, когда / если загружается библиотека). - person Rai; 29.07.2014
comment
@Rai: Вы сказали Преимущество статической компоновки в том, что она позволяет компоновщику вырезать неиспользуемый код, что позволяет уменьшить использование памяти приложением. Однако вы должны беспокоиться о версиях среды выполнения C. но я думаю, что это неправильно, поскольку чередование включает только удаление файлов, которые содержат символы в исполняемом архиве. Поскольку он использует отдельный файл (это верно для большинства форматов исполняемых файлов) из исполняемого кода, почему ОС должна загружать его в ОЗУ, поскольку ОС знает, что символы не нужны. Это то, что я хотел иметь в виду. - person user2284570; 30.07.2014
comment
Я знаю, что вопрос определяет C ++, но стоит обновить свой ответ, чтобы сказать, что динамическое связывание позволяет различным языкам программирования взаимодействовать. - person Philluminati; 05.09.2014
comment
Плагины всегда требуют динамического связывания. Это неверно. Некоторые модели плагинов, такие как Apple AudioUnits, могут запускать плагин в отдельном процессе и использовать IPC. Это более безопасная альтернатива динамической компоновке для плагинов (плагин не может вызвать сбой хоста). Предложите обновить ответ. Для подключаемых модулей может потребоваться динамическое связывание или что-то подобное. - person Taylor; 12.10.2015
comment
Хммм ... Я бы сам не назвал эти плагины, но я полагаю, что они служат той же цели. - person dmckee --- ex-moderator kitten; 12.10.2015
comment
@MarkRansom: ошибочно думать, что проблема потребления ресурсов связана только с оперативной памятью. Кэш-память - гораздо более ограниченный ресурс, чем оперативная память, и динамическое связывание также снижает ее использование. - person intelfx; 06.03.2016
comment
@MarkRansom Если каждый процесс статически связан со стандартной библиотекой, таким образом дублируя стандартную библиотеку, то каждый раз, когда процесс вызывает общую функцию, кеш будет недействителен; одна общая функция будет заменена другой без всякой пользы. Динамическое связывание, безусловно, может предотвратить промахи кеша. - person autistic; 01.09.2017
comment
Статическая компоновка запускается быстрее, чем динамически подключаемые библиотеки. Не могли бы вы объяснить заявление? По моему мнению, в статических связанных библиотеках мы загружаем все разделяемые библиотеки в исполняемый файл, поэтому при запуске это должно занимать больше времени, чем динамически подключаемые библиотеки. - person Zephyr; 10.11.2017
comment
@Zephyr Хм. С самого начала (когда программе ничего не нужно в памяти) статический связанный код должен загружаться быстрее, потому что [a] статическое связывание обычно включает только вызываемые библиотечные функции (поэтому требуется меньше кода для загрузки) и [b] для тех, кто все еще у вращающихся дисков время поиска, чтобы найти начало отдельных файлов. Но любая конкретная динамическая библиотека может уже находиться в памяти (вероятно, это некоторые очень распространенные библиотеки), а время поиска на SSD тривиально. - person dmckee --- ex-moderator kitten; 10.11.2017
comment
@dmckee При статической компоновке все необходимые библиотеки встроены в исполняемый файл при самом запуске, верно? Так как размер больше, для загрузки кода в память потребуется больше времени, чем при динамической компоновке, когда размер исполняемого файла меньше во время запуска, верно? - person Zephyr; 10.11.2017
comment
@Zephyr В полнофункциональных системах статическая компоновка включает только те подпрограммы из библиотеки , которые используются программой. Не вся библиотека: только те части, которые использует программа. Вспомните, насколько драгоценным был размер рабочего набора на машинах прошлого: люди долго думали об этом. - person dmckee --- ex-moderator kitten; 10.11.2017
comment
@dmckee Значит, размер исполняемого файла не имеет ничего общего со временем запуска программы? - person Zephyr; 10.11.2017
comment
@Zephyr Чтобы загрузить статически связанную программу, вы загружаете программный код и то подмножество кода библиотеки, которое используется программой. Чтобы загрузить динамически скомпонованную программу, вы загружаете только программные коды и все библиотеки, которые еще не находятся в памяти. Если ни одна из библиотек уже не была в памяти, последняя может быть больше первой. Теперь немного о том, что «если ни одна из библиотек уже не присутствовала», - вот почему в сообщениях говорится, что может, а не есть. - person dmckee --- ex-moderator kitten; 10.11.2017
comment
@dmckee Хорошо, понятно! Даже если все библиотеки присутствуют в памяти, то слишком динамическое связывание займет больше времени, верно из-за одного уровня косвенности? - person Zephyr; 10.11.2017
comment
@dmckee Пожалуйста, поправьте меня, если я ошибаюсь, время выполнения вызова одной и той же функции несколько раз с одним и тем же вводом может быть нестабильным при использовании динамических библиотек в Windows, потому что операционная система должна управлять вызовами, и иногда выполнение кода ожидает вызова функции, потому что есть очередь потоков и приоритеты, а при статической компоновке весь код загружен в память и не возникает этой проблемы? - person Stav Bodik; 23.08.2018
comment
@Stav Понятия не имею. Я практически ничего не знаю о внутреннем устройстве Windows. - person dmckee --- ex-moderator kitten; 24.08.2018

1) основан на том факте, что при вызове функции DLL всегда используется дополнительный косвенный переход. Сегодня это обычно незначительно. Внутри DLL есть дополнительные накладные расходы на процессоры i386, потому что они не могут генерировать независимый от позиции код. На amd64 скачки могут относиться к программному счетчику, так что это огромное улучшение.

2) Это правильно. При оптимизации, основанной на профилировании, обычно можно добиться 10-15% производительности. Теперь, когда скорость процессора достигла своего предела, возможно, стоит это сделать.

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

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

По этим причинам, если нет реальной необходимости в библиотеках DLL, просто используйте статическую компиляцию.

РЕДАКТИРОВАТЬ (чтобы ответить на комментарий, подчеркнув пользователем)

Вот хороший ресурс о проблеме независимого от позиции кода http://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/

Как объяснялось, x86 не имеет их AFAIK ни для чего другого, кроме диапазонов 15-битных переходов, а не для безусловных переходов и вызовов. Вот почему функции (от генераторов), имеющие более 32К, всегда были проблемой и нуждались в встроенных трамплинах.

Но в популярных ОС x86, таких как Linux, вам не нужно беспокоиться о том, что файл .so / DLL не создается с помощью переключателя gcc -fpic (который требует использования таблиц косвенного перехода). Потому что, если вы этого не сделаете, код будет просто исправлен, как обычный компоновщик переместил бы его. Но при этом он делает сегмент кода недоступным для совместного использования, и ему потребуется полное отображение кода с диска в память и прикосновение ко всему, прежде чем его можно будет использовать (очистка большей части кешей, попадание в TLB) и т. Д. Было время когда это считалось медленным.

Так что пользы больше не будет.

Я не помню, какая ОС (Solaris или FreeBSD) дала мне проблемы с моей системой сборки Unix, потому что я просто не делал этого и удивлялся, почему она вылетает, пока я не применил -fPIC к gcc.

person Lothar    schedule 03.01.2010
comment
Мне нравится этот ответ, потому что он был единственным, в котором были затронуты вопросы, которые я затронул в вопросе. - person Eloff; 05.01.2010
comment
Было бы интересно получить ссылки на технические характеристики этих DLL и сравнение различных операционных систем. - person UncleZeiv; 16.04.2010
comment
Вроде бы нормально, но скорость процессора точно не достигла своего предела. - person Aidiakapi; 15.04.2015

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

person Mark Ransom    schedule 03.01.2010
comment
Пока конечный пользователь может повторно подключиться к коду LGPL (например, потому что вы предоставляете свой исходный код или скомпилированные объектные файлы вместе с вашим программным обеспечением), тогда можно использовать статические ссылки. Кроме того, если ваше программное обеспечение предназначено для внутреннего использования (т. Е. Для использования только в вашей организации, а не для распространения), вы можете установить статическую ссылку. Это применимо, например, к серверное программное обеспечение, где сервер не распространяется. - person JBentley; 10.01.2014
comment
Не понимаю. Не могли бы вы дать мне больше источника (или уточнить подробности), чтобы оценить то, что вы написали? - person Baskaya; 24.10.2015
comment
@Thorn см. раздел лицензии LGPL 4.d + e. Вам необходимо либо распространять в форме, требующей от пользователя ссылки, либо распространять общую (динамическую) библиотеку. - person Mark Ransom; 24.10.2015

Я согласен с пунктами, упомянутыми dnmckee, плюс:

  • Статически связанные приложения может быть проще развертывать, поскольку существует меньше или нет дополнительных зависимостей файлов (.dll / .so), которые могут вызвать проблемы, если они отсутствуют или установлены в неправильном месте.
person stakx - no longer contributing    schedule 03.01.2010
comment
Стоит отметить, что компилятор Go от Google будет только статически компилировать двоичные файлы, главным образом по этой причине. - person Hut8; 05.03.2014

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

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

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

person Rob Wells    schedule 03.01.2010
comment
очень хороший момент, я недавно пытался сделать это с каким-то кодом, который у меня есть на работе, но компилирование всего статического оказалось на удивление раздражающим, и я просто сдался - person UncleZeiv; 16.04.2010

1 / Я участвовал в проектах, где проводилось тестирование динамического и статического связывания, и разница не была определена достаточно мала, чтобы переключиться на динамическое связывание (я не участвовал в тесте, я просто знаю вывод)

2 / Динамическое связывание часто связано с PIC (код, независимый от позиции, код, который не нужно изменять в зависимости от адреса, по которому он загружен). В зависимости от архитектуры PIC может вызвать другое замедление, но это необходимо для того, чтобы получить выгоду от совместного использования динамически связанной библиотеки между двумя исполняемыми файлами (и даже двумя процессами одного и того же исполняемого файла, если ОС использует рандомизацию адреса загрузки в качестве меры безопасности). Я не уверен, что все ОС позволяют разделить эти две концепции, но Solaris и Linux это делают, а также ISTR, что и HP-UX.

3 / Я участвовал в других проектах, в которых использовалось динамическое связывание для функции «простого исправления». Но этот «легкий патч» делает распространение небольших исправлений немного проще, а сложные - кошмаром для управления версиями. Мы часто заканчивали тем, что вынуждены были все продвигать, а также отслеживали проблемы на сайте клиента из-за того, что токеном была неправильная версия.

Я пришел к выводу, что я использовал статические ссылки, за исключением:

  • для таких вещей, как плагины, которые зависят от динамического связывания

  • когда важно совместное использование (большие библиотеки, используемые несколькими процессами одновременно, такие как среда выполнения C / C ++, библиотеки GUI, ... которые часто управляются независимо и для которых строго определен ABI)

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

person AProgrammer    schedule 03.01.2010
comment
Некоторые операционные системы для процессоров, отличных от PIC или дорогостоящих процессоров PIC, подготавливают динамические библиотеки для загрузки по определенному адресу в памяти, и если они могут это сделать, они просто сопоставляют копию библиотеки каждому процессу, который с ней связан. Это значительно снижает накладные расходы на PIC. По крайней мере, OS X и некоторые дистрибутивы Linux делают это, насчет Windows я не уверен. - person Andrew McGregor; 03.01.2010
comment
Спасибо, Эндрю, я не знал, что некоторые дистрибутивы Linux используют это. У вас есть ссылка, по которой я могу следовать, или ключевое слово, по которому я могу поискать, чтобы узнать больше? (FWIW Я слышал, что Windows делает вариант этого, но Windows слишком далеко от моей компетенции, чтобы я упоминал об этом). - person AProgrammer; 03.01.2010
comment
Я думаю, что ключевое слово, которое вы ищете, - это предварительная ссылка - она ​​подготавливает библиотеку к быстрой загрузке по определенному адресу, чтобы ускорить запуск программы. - person Blaisorblade; 15.01.2013

Здесь подробно обсуждаются общие библиотеки Linux и их влияние на производительность.

person nos    schedule 03.01.2010
comment
+1 за ссылку на Drepper DSO howto, который должен прочитать каждый, кто создает библиотеки для Linux. - person janneb; 03.01.2010

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

Еще лучшим примером может быть OpenGL. OpenGl - это API, который по-разному реализован AMD и NVidia. И вы не можете использовать реализацию NVidia на карте AMD, потому что оборудование другое. Из-за этого вы не можете статически связать OpenGL с вашей программой. Здесь используется динамическое связывание, позволяющее оптимизировать API для всех платформ.

person Arne    schedule 12.02.2015

На самом деле это довольно просто. Когда вы вносите изменения в исходный код, вы хотите подождать 10 минут или 20 секунд? Двадцать секунд - это все, с чем я могу мириться. Помимо этого, я либо достаю меч, либо начинаю думать о том, как я могу использовать отдельную компиляцию и линковку, чтобы вернуть ее в зону комфорта.

person Hans Passant    schedule 03.01.2010
comment
Я на самом деле не тестировал разницу в скорости компиляции, но я бы использовал динамическую ссылку, если бы она была значительно быстрее. Boost и так делает достаточно плохих вещей для моего времени компиляции. - person Eloff; 05.01.2010

В Unix-подобных системах динамическое связывание может усложнить жизнь «root» при использовании приложения с общими библиотеками, установленными в труднодоступных местах. Это связано с тем, что динамический компоновщик обычно не обращает внимания на LD_LIBRARY_PATH или его эквивалент для процессов с привилегиями root. Таким образом, иногда статические ссылки спасают положение.

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

person Jonathan Leffler    schedule 04.01.2010
comment
Пункт о LD_LIBRARY_PATH не является препятствием для использования разделяемых библиотек, по крайней мере, не в GNU / Linux. Например. если вы поместите разделяемые библиотеки в каталог ../lib/ относительно файла программы, то с помощью цепочки инструментов GNU опция компоновщика -rpath $ORIGIN/../lib будет указывать поиск библиотеки из этого относительного местоположения. Затем вы можете легко переместить приложение вместе со всеми связанными общими библиотеками. Используя этот трюк, нет проблем с наличием нескольких версий приложения и библиотек (при условии, что они связаны, в противном случае вы можете использовать символические ссылки). - person FooF; 20.06.2012
comment
›Для процессов с привилегиями root. Я думаю, вы говорите о программах setuid, запускаемых пользователями без полномочий root - иначе это не имеет смысла. И двоичный файл setuid с библиотеками в нестандартных местах - это странно, но поскольку только root может устанавливать эти программы, он также может редактировать /etc/ld.so.conf для этого случая. - person Blaisorblade; 15.01.2013

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

Также см. DLL Hell. Это сценарий, в котором загружаемая ОС не та DLL, которая поставляется с вашим приложением, или не той версии, которую ожидает ваше приложение.

person Thomas Matthews    schedule 03.01.2010
comment
Важно отметить, что существует ряд контрмер, позволяющих избежать ада DLL. - person ocodo; 26.12.2012

Static linking - это процесс во время компиляции, когда связанный контент копируется в основной двоичный файл и становится одним двоичным файлом.

Минусы:

  • время компиляции больше
  • выходной двоичный файл больше

Dynamic linking - это процесс во время выполнения, когда загружается связанный контент. Эта техника позволяет:

  • обновить связанный двоичный файл без перекомпиляции основного, что повысит ABI стабильность [About]
  • имеет единственную общую копию

Минусы:

  • время начала медленнее (необходимо скопировать связанный контент)
  • ошибки компоновщика возникают во время выполнения

[Статическая и динамическая платформа iOS]

person yoAlex5    schedule 10.04.2020

Еще один вопрос, который еще не обсуждается, - это исправление ошибок в библиотеке.

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

С динамической компоновкой вы просто перестраиваете и распространяете динамическую библиотеку, и все готово.

person R Samuel Klatchko    schedule 03.01.2010

Статическая компоновка включает файлы, которые нужны программе, в одном исполняемом файле.

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

(DLL = библиотека динамической компоновки)

Динамически связанные исполняемые файлы компилируются быстрее и не требуют больших ресурсов.

person Nykal    schedule 05.09.2017

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

person Govardhan Murali    schedule 11.10.2016

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

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

Чрезвычайно распространенный пример - устройства, использующие системы GNU / Linux, использующие Busybox. Я довел это до крайности с помощью NetBSD, создав загрузочный образ системы i386 (32-разрядный), который включает в себя как ядро, так и его корневую файловую систему, последняя содержит единственный статически связанный (crunchgen) двоичный файл с жесткими ссылками на все программы, который сам содержит все (ну, по крайней мере, 274) из стандартные полнофункциональные системные программы (большинство, кроме набора инструментов), и его размер составляет менее 20 мегабайт (и, вероятно, он очень комфортно работает в системе только с 64 МБ памяти (даже с корневой файловой системой несжатый и полностью в ОЗУ), хотя мне не удалось найти такой маленький, чтобы протестировать его).

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

Однако это еще не все. Я также обычно создаю и использую установки операционной системы NetBSD для своих полных систем разработки путем статической компоновки всех двоичных файлов. Несмотря на то, что для этого требуется гораздо больше дискового пространства (всего ~ 6,6 ГБ для x86_64 со всем, включая инструментальную цепочку и статическую привязку X11) (особенно если сохранить полные таблицы символов отладки, доступные для всех программ, еще ~ 2,5 ГБ), результат все равно в целом работает быстрее, а для некоторых задач даже использует меньше памяти, чем типичная система с динамической компоновкой, предназначенная для совместного использования кодовых страниц библиотеки. Диск дешевый (даже быстрый диск), и память для кеширования часто используемых файлов на диске также относительно дешевая, но циклы ЦП на самом деле не такие, и оплата ld.so начальных затрат за каждый процесс, который запускается каждый раз, когда он Запуск будет отнимать часы и часы циклов ЦП от задач, требующих запуска многих процессов, особенно когда одни и те же программы используются снова и снова, например, компиляторы в системе разработки. Статически связанные программы инструментальной цепочки могут сократить время сборки всей многоархитектурной ОС для моих систем на часов. Мне еще предстоит встроить инструментальную цепочку в свой единственный crunchgen бинарный файл, но я подозреваю, что когда я это сделаю, время сборки будет сэкономлено больше благодаря выигрышу для кэша ЦП.

person Greg A. Woods    schedule 28.07.2017

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

person Phil K    schedule 10.09.2020