Почему запуск приложения в Linux происходит медленнее при использовании общих библиотек?

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

  •  05-07-2019
  •  | 
  •  

Вопрос

На встроенном устройстве, над которым я работаю, время запуска является важной проблемой.Все приложение состоит из нескольких исполняемых файлов, которые используют набор библиотек.Поскольку место во ФЛЭШ-памяти ограничено, мы хотели бы использовать общие библиотеки.

Приложение работает как обычно, когда оно скомпилировано и связано с разделяемыми библиотеками, а объем ФЛЭШ-памяти сокращается, как и ожидалось.Разница с версией, которая связана со статическими библиотеками, заключается в том, что время запуска приложения примерно на 20 секунд больше, и я понятия не имею, почему.

Приложение работает на процессоре ARM9 с частотой 180 МГц и операционной системой Linux 2.6.17, 16 МБ ФЛЭШ-памяти (файловая система JFFS) и 32 МБ оперативной памяти.

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

Решение

Потому что общие библиотеки должны быть связаны во время выполнения, обычно с помощью dlopen() или чего-то подобного.Для статических библиотек такого шага нет.

Редактировать:еще несколько деталей.dlopen должен выполнять следующие задачи.

  • Найдите общую библиотеку
  • Загрузите его в память
  • Рекурсивно загружать все зависимости (и их зависимости ....)
  • Разрешить все символы

Для выполнения этого требуется довольно много операций ввода-вывода.

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

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

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

Это прекрасный пример классического компромисса между скоростью и пространством.

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

или

У вас могут быть общие библиотеки, которые занимают меньше места, но и больше времени на загрузку.

Так что решите, чем вы хотите пожертвовать.

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

(В качестве исторической заметки оригинальный Netscape navigator в Linux / Unix был статически связанным исполняемым файлом big fat).

Это может помочь другим с подобными проблемами:

Причина, по которой запуск в моем случае занял так много времени, заключалась в том, что настройка GCC по умолчанию - экспортировать все символы внутри библиотеки. Большим улучшением является установка параметра компилятора " -fvisibility = hidden ".

Все символы, которые должна экспортировать библиотека, должны быть дополнены оператором

__ attribute__ ((видимость (" по умолчанию ")))

см. gcc wiki
и очень хорошая статья как писать общие библиотеки

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

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

Итак, извините, я не могу не сказать почему, но я думаю, что это проблема с вашим устройством / ОС ARM. Вы пробовали вводить код запуска или статически связываться с 1 из наиболее часто используемых библиотек, чтобы увидеть, имеет ли это большое значение. Также поместите разделяемые библиотеки в тот же каталог, что и приложение, чтобы сократить время, необходимое для поиска в ФС библиотеки.

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

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

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