[О блоге] [наверх] [пред] [2021-09-17 10:42:50+03:00] [4e9253c8bdec3a221e61ab5364de0c73585e8594]

Роб Пайк про Docker и динамическую линковку

https://minnie.tuhs.org/pipermail/tuhs/2021-September/024417.html
Если бы не популяризация динамической линковки, то Docker бы не взлетел.
Звучит логично и правдоподобно: со статической линковкой нету ада
библиотечных зависимостей. Ещё один камень в сторону динамической линковки!
К Docker у меня исключительно негативное отношение.

    [оставить комментарий]
    комментарий 0:
    From: Алексей
    Date: 2021-09-17 12:11:44Z
    
    Проблема статической линковки в том, что она тащит в бинарник тонны неиспользуемого мусора даже для такого простого языка как C, где вроде как должно быть возможно выкинуть из бинарника весь тот код, который там реально не используется.
    Так, если я создаю простейший Hello World на C с использованием SDL, который всего лишь выводит пустое окно, то при динамической линковке он будет весить только 3Кб, а если слинковать SDL статически - больше метра (почти полный размер данной библиотеки!).
    Нет, я конечно понимаю, что там есть какой-то инициализационный код, но блин не 90% же кодовой базы! То есть линкер засунул в бинарник тонны балласта, который очевидно никогда и ни при каких условиях не выполняется.
    И это всего лишь C. В случае C++ ситуация резко ухудшается. Попробуйте слинковать статически Qt-проект, даже самый простой, у вас там десятки Мб сразу выйдут, потому что из-за особенностей C++ не существует способа достоверно определить, будет данный код исполняться хоть когда-то или же нет.
    Когда же у нас сам язык динамический по своей природе, типа C# или Java, тут и вовсе нормальный линкер сделать невозможно в принципе, и Dependency Hell неизбежен. Одно время даже была такая шутка: "Программы на Java по-настоящему кроссплатформенны, на любом железе НЕ работают абсолютно одинаково". Даже сейчас запустить какой-нибудь jar-файл - это минимум 15 мин трахотни с зависимостями, начиная с подбора правильной версии/сборки JRE.
    
    комментарий 1:
    From: Sergey Matveev
    Date: 2021-09-17 13:29:13Z
    
    *** Алексей [2021-09-17 15:11]:
    >Проблема статической линковки в том, что она тащит в бинарник тонны неиспользуемого мусора
    
    А это уже вопрос, в том числе, как собрана эта библиотека. Библиотеки
    разбиваются на секции -- грубо говоря, секция ELF-а это неделимый атом.
    Если в секции содержится foo() и bar() функции, а нам нужна только
    foo(), то всё равно при линковке будет засунута вся секция, включая этот
    bar(). Если указать -ffunction-sections, то каждая функция будет в своей
    отдельной секции и это позволит не включать ничего что не используется.
    Я не раз замечал что многие не выставляют даже этот простой аргумент и
    поэтому их статические библиотеки при линковке могут быть огромными,
    действительно.
    
    >Так, если я создаю простейший Hello World на C с использованием SDL, который всего лишь выводит пустое окно, то при динамической линковке он будет весить только 3Кб
    
    Вот только в оперативную память будет загружен всё равно мегабайт
    динамической библиотеки. И даже если для SDL всё равно требуется 90% его
    кода, то динамическая библиотека была бы tradeoff-ом между местом на
    диске и дорогостящими CPU операциями по динамической линковке в
    real-time, так сказать. Статический файл я просто загружаю и передаю ему
    управление, а с динамической линковкой, я вон уже как-то показывал в
    одном из комментариев к ImageMagick-у в своём блоге, что 300мс (!!!)
    тратится просто на запуск convert утилиты и никак это время не
    сократить, которое просто "подключает" динамические загруженные
    библиотеки к новому загружаемому процессу. Уж извините, но нет, я готов
    потратить лишний мегабайт хоть для каждого .exe-шника, лишь бы впустую
    не тратить тьму времени, которое я даже визуально могу заметить, при
    *каждом* запуске этого .exe.
    
    Я думаю или тут SDL так устроен что он почти весь свой код использует и
    поэтому он линкуется, или он как-то скомпонован криво или банально
    собран без каких-нибудь -ffunction-sections. Если написать printf("hello
    world"), то при статической линковке только printf будет включена (ну
    что ей там нужно, по мелочам) в исполняемый файл, а не вся libc. При
    динамической линковке, даже когда нам нужен только printf, то всё равно
    полностью весь libc будет загружен в память. С libc то это не проблема,
    ибо его все используют, а вот с остальными уже может стать проблемой.
    
    Вообще-то именно как-раз возможность не включать неиспользуемые вещи и
    есть основная фишка статической линковки. То что не все умеют "её
    готовить" -- это другой вопрос.
    
    >Когда же у нас сам язык динамический по своей природе, типа C# или Java, тут и вовсе нормальный линкер сделать невозможно в принципе
    
    Потому что этот подход (всё на свете динамическое) -- просто не нужен,
    создаёт сплошные проблемы. Вызывать сторонние функции можно и через RPC,
    пускай даже ценой небольшой просадки по производительности. Можно
    выдумывать много проблем для которых динамическая линковка бы была
    нужна, а можно не создавать этих проблем и вовсе.