Издевательства над динамическим связыванием

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

Издевательства над динамическим связыванием

Сообщение daesher » 14.01.2016 23:23:08

Часть первая. FreePascal.
Итак, думаю, весьма очевидна главная проблема FreePascal: он не может поместить часть сгенерированного кода в динамическую библиотеку. Как следствие, он генерирует каждый файл огромного размера, помещая весь свой код в каждый файл. Свои плюсы в подходе "Всё своё ношу с собой", конечно же, есть, но если попробовать создать целую систему с десятком паскалевских файлов (о формах lazarus я вообще молчу), то мы получим огромный перерасход и дискового пространства, и, как следствие, места на сервере и расхода трафика у качающих. Короче, всё плохо.
Но ведь в linux же есть такой хороший механизм - gcc --shared, который может всё общее свести в одну библиотеку!
Как-то года 3-4 назад я этим уже баловался, но тогда не сильно преуспел, да и язык фактически был другим, сейчас решил повторить.
Итак, на чём я тестировал. Компилятор стандартный 3.0.0 (а для trunk и не стоит делать библиотек). Lazarus, забегая вперёд, взял 1.6RC1.
Система - ubuntu wily amd64. Проект для начала сделал простейший (tst.pas):
Код: Выделить всё
program tst;
uses Classes,SysUtils,x;
begin
  Writeln(Trim('Привет, мир!'));
end.

Модули Classes и SysUtils нужны чтобы было что загонять в библиотеку (затем же и функция Trim), а модуль x - чтобы FPC запустил динамическую компоновку (иначе будет создан скрипт для статической компоновки, и присоединить к файлу нему библиотеку окажется непросто).
Итак, fpc tst.pas - и передо мной файл tst. Я его переименовал в tst.nolib - размер 706 624 байт. Так себе, но для такой ерунды хотелось бы меньше. Сюда вложил сжатым в gz -
tst.nolib.gz
(240.1 КБ) Скачиваний: 422
.
Следующее действие - разбить на две части: библиотеку и сам файл. Ключ -Cn заставит FPC опустить стадию компоновки, получив link.res.
Итак, у нас появился link.res - внимательно смотрим. Ищем секции INPUT - их три.
Первая самая интересная - сначала там идут всякие служебные файлы prt, cpt. Их трогать не надо. Потом идут файлы проекта вперемешку с стандартными паскалевскими файлами. Вот последние и перемещаем в отдельный файл (секций не надо). В начало дописываем gcc -o <Название библиотеки> --shared
а все остальные строки заканчиваем обратным слешем. Туда же бросаем на всякий случай всё из второй секции INPUT.
Результат:

Код: Выделить всё
gcc --shared -o libfpc-3.0.so
/usr/lib/fpc/3.0.0/units/x86_64-linux/rtl/system.o
/usr/lib/fpc/3.0.0/units/x86_64-linux/rtl/classes.o
/usr/lib/fpc/3.0.0/units/x86_64-linux/rtl/sysutils.o
/usr/lib/fpc/3.0.0/units/x86_64-linux/x11/x.o
/usr/lib/fpc/3.0.0/units/x86_64-linux/rtl/objpas.o
/usr/lib/fpc/3.0.0/units/x86_64-linux/rtl/types.o
/usr/lib/fpc/3.0.0/units/x86_64-linux/rtl/typinfo.o
/usr/lib/fpc/3.0.0/units/x86_64-linux/rtl/rtlconsts.o
/usr/lib/fpc/3.0.0/units/x86_64-linux/rtl/linux.o
/usr/lib/fpc/3.0.0/units/x86_64-linux/rtl/unix.o
/usr/lib/fpc/3.0.0/units/x86_64-linux/rtl/errors.o
/usr/lib/fpc/3.0.0/units/x86_64-linux/rtl/sysconst.o
/usr/lib/fpc/3.0.0/units/x86_64-linux/rtl/unixtype.o
/usr/lib/fpc/3.0.0/units/x86_64-linux/rtl/baseunix.o
/usr/lib/fpc/3.0.0/units/x86_64-linux/rtl/unixutil.o
/usr/lib/fpc/3.0.0/units/x86_64-linux/rtl/ctypes.o
-lX11

Этот файл можно запустить - и у нас в каталоге появилась библиотека. Ничего так весит, после strip 1,5 Мб (точнее 1 549 192 байта) - но она же может использоваться для нескольких проектов! Там у нас всё для паскаля.
Вот ссылка на библиотеку: http://daesher.narod.ru/nolib/libfpc-3.0.so
Теперь правим подрезанный link.res - во вторую секцию INPUT надо добавить -l<краткое название библиотеки>. Третью секцию трогать не надо. Привожу кусок link.res без начала и конца после третьей секции INPUT (он всё равно собирается!)
Код: Выделить всё
INPUT(
/usr/lib/fpc/3.0.0/units/x86_64-linux/rtl/cprt0.o
/usr/lib/x86_64-linux-gnu/crti.o
/usr/lib/gcc/x86_64-linux-gnu/5/crtbegin.o
tst.o
)
INPUT(
-lX11
-lfpc-3.0
)
GROUP(
-lc
)
INPUT(
/usr/lib/gcc/x86_64-linux-gnu/5/crtend.o
/usr/lib/x86_64-linux-gnu/crtn.o
)

Запускаем ppas.sh - и - о чудо - у нас файл в 8 Кб.
http://daesher.narod.ru/nolib/tst.noext
Запускать так
LD_LIBRARY_PATH=. ./tst
Или скопировать библиотеку куда-нибудь в стандартное место.
Под Windows не проверял.




Добавлено спустя 14 минут 17 секунд:
Часть вторая - графическое приложение Lazarus.
Взял за основу мой кластерный анализ - возможно, сделан коряво, где-то когда-то публиковал, но не помню. По GPL выкладываю исходники
clanalysis.tar.gz
(23.7 КБ) Скачиваний: 415
.
Теперь запускаем Lazarus и правим параметры проекта: вырубаем отладку вообще (иначе будут проблемы), ставим в дополнительные параметры -Cn и "собираем".
Получаем нужный нам link.res, делим его на части.
Честно скажу: проверил я на другом проекте, вырезав всё паскалевское и лазарусное в liblcl.so "весом" в 13 мегабайт:
http://daesher.narod.ru/nolib/liblcl.so.xz (я её, конечно, сжал xz).
Скрипт к ней вот: http://daesher.narod.ru/nolib/laz.sh (толку от него уже мало - пути относительно моего компьютера).
После этого подрезал link.res (он есть в исходном архиве). В итоге сам файл с интерфейсом вполне скромный, на "дельфевском" уровне:
http://daesher.narod.ru/nolib/ClAnalysis.noext
Чуть больше 250 Кб (по сравнению с исходным, без библиотеки - 5,5 Мб) . И ведь работает!!!
Выигрыш, таким образом, начинается только с 3-4 файлов с GUI.

Вывод: над этим надо работать. Думаю, есть смысл автоматизировать процесс если не создания библиотек, то хотя бы их подключения - создать надстройку над FPC.
daesher
постоялец
 
Сообщения: 221
Зарегистрирован: 09.03.2010 22:17:14

Re: Издевательства над динамическим связыванием

Сообщение zub » 14.01.2016 23:55:07

Лучше подождать пока вот это будет http://svn.freepascal.org/cgi-bin/viewv ... /packages/ допилено. еще лучше помочь в допиливании))
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: Издевательства над динамическим связыванием

Сообщение daesher » 15.01.2016 00:29:02

zub писал(а):Лучше подождать пока вот это будет http://svn.freepascal.org/cgi-bin/viewv ... /packages/ допилено. еще лучше помочь в допиливании))

Как говорится, обещанного 3 года ждут. На самом деле - куда больше. Слово "package" уже сколько лет в синтаксисе FPC? А результат?
За ветку, конечно, спасибо, посмотрю, что она может. Правда, разработка там идёт не очень...
И хоть бы один тест о том, как это работает (в Delphi понятно, там пакеты подключаются через IDE).
Нет, быстрее сделать такой workaround, чтобы хоть что-то было.

Добавлено спустя 10 часов 29 минут 23 секунды:
Короче, ветка создаёт библиотеки (пакеты) уже без ошибок. Как сказать, что их надо использовать? Насколько я помню, в Delphi такая опция выставляется в IDE, а аналогов в коде я не нашёл.
Загружать пакет динамически я не хочу - ведь в нём лежат модули System и Classes.
daesher
постоялец
 
Сообщения: 221
Зарегистрирован: 09.03.2010 22:17:14

Re: Издевательства над динамическим связыванием

Сообщение zub » 15.01.2016 11:13:43

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

зы. возможно поможет http://wiki.freepascal.org/packages
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: Издевательства над динамическим связыванием

Сообщение Sharfik » 15.01.2016 18:49:12

Что хуже платить Охренеть сколько за среду которая для тебя деньги не отобьет свои или не платить и иметь лишние мегабайты?
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 791
Зарегистрирован: 20.07.2013 01:04:30

Re: Издевательства над динамическим связыванием

Сообщение daesher » 15.01.2016 21:13:07

zub писал(а):зы. возможно поможет http://wiki.freepascal.org/packages

Я уже больше 3-4 лет как эту страницу смотрю. Всё планы, планы, что это бы дало... А как конкретно их подключить - такого там нет.
zub писал(а):Насколько я понимаю без System программу не создать, поэтому в пакет это хозяйство не сложить

УМВР! То, что предлагаю я, легко включает модуль System. Осталось только всё это автоматизировать. Ну ладно, пусть - автоматизировать использование библиотек-пакетов, создать их можно и вручную. Сделать надстройку над fpc, которая будет вызываться вместо него (хотя fpc сам является такой надстройкой). Не так уж это и сложно, если честно. Да, полетит контроль версий у пересобирающегося по поводу и без повода lazarus, но переживём.

Добавлено спустя 5 минут 53 секунды:
Sharfik писал(а):Что хуже платить Охренеть сколько за среду которая для тебя деньги не отобьет свои или не платить и иметь лишние мегабайты?

Лучше всего сделать "костыль", и ни за что не платить, и не иметь лишних мегабайтов.
daesher
постоялец
 
Сообщения: 221
Зарегистрирован: 09.03.2010 22:17:14

Re: Издевательства над динамическим связыванием

Сообщение SSerge » 16.01.2016 06:33:23

daesher писал(а):Лучше всего сделать "костыль"


Не набегаешься особо на костылях-то...
Насколько помню, главной проблемой использования динамических библиотек в fpc, является существующий код менеджера памяти и то, что для динамической библиотеки нужно передавать его вручную из вызывающего кода, иначе (С) мракъ, содомъ и адъ, связанный с референсными типами данных, коих преизряднейше. В том числе среди промежуточных переменных, генерируемых компилятором. Подозреваю, что ваши костыли могут сломаться от этого же эффекта.
SSerge
энтузиаст
 
Сообщения: 971
Зарегистрирован: 12.01.2012 05:34:14
Откуда: Барнаул

Re: Издевательства над динамическим связыванием

Сообщение daesher » 16.01.2016 18:59:20

SSerge писал(а): В том числе среди промежуточных переменных, генерируемых компилятором. Подозреваю, что ваши костыли могут сломаться от этого же эффекта.

Не уверен, хотя несколько файлов, завязанных на одну и ту же библиотеку, я в параллель не запускал. Проблемы динамических библиотек fpc здесь как раз исчезают (только все ли?), если эти проблемы связаны с дублированием подсистем: есть подсистема собственно dll со своим модулем System, со своим менеджером памяти, и есть исполняемый файл со всеми такими же функциями, но отдельно. И вот они вполне могут друг с другом конфликтовать.
У меня подход совсем другой: дублирования кода НЕТ. Код модуля System (вместе с другими) банально выносится в библиотеку, а в самом исполняемом файле его нет! (от слова вообще). Служебные файлы, прилинкованные к исполняемому файлу, отсутствуют в библиотеке. Результат - в отдельности исполняемый файл и библиотека (точнее, .so linux, на dll windows я это ещё не проверял) не существуют друг без друга (ну или без аналогичного другого исполняемого файла ПРИ условии, что этот файл использует библиотеки вообще, а не представляет из себя нечто статическое, к которому "привинчивается" библиотека). Дублирования нет. Менеджер памяти один.
Если кто-то попробует использовать такую библиотеку без паскаля (например, подключит её к сишной программе), то он замучается разбираться с паскалевскими символами, куски которых таки остались в исполняемом файле. Может, ему и удастся их заэмулировать. Но зачем?
Короче, набросал я времянку-прогу, которая позволит собирать всё, сейчас тестирую.

Добавлено спустя 2 часа 40 минут 42 секунды:
Вот программа-времянка - fpc_pk версии 0.0.1. Внутри - readme и примеры.
Вложения
fpcpk.tar.gz
(10.94 КБ) Скачиваний: 439
daesher
постоялец
 
Сообщения: 221
Зарегистрирован: 09.03.2010 22:17:14

Re: Издевательства над динамическим связыванием

Сообщение MageSlayer » 21.02.2016 20:26:40

Вопрос немного не по теме, но все же.
Есть ли выигрыш по времени линковки проекта из-за вынесения кода в .so?

Меня интересует ускорение линковки проектов с GUI при сборке из Лазаруса.
Компилятор собирает достаточно быстро, а вот линковщик уже требует до 10 сек.
MageSlayer
постоялец
 
Сообщения: 216
Зарегистрирован: 07.09.2006 12:30:44

Re: Издевательства над динамическим связыванием

Сообщение zub » 15.04.2016 15:08:06

Глянул последние комиты http://svn.freepascal.org/cgi-bin/viewv ... /packages/ потихоньку в транк мержат.
Так глядишь скоро пакетами разживемся))
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: Издевательства над динамическим связыванием

Сообщение ger0strat » 16.04.2016 09:00:41

daesher писал(а):Чуть больше 250 Кб (по сравнению с исходным, без библиотеки - 5,5 Мб)

Уж простите мне мой скептицизм, но меня гложут сомнения, что не выставлены правильные ключи компиляции.
Да и даже если все так, совершенно не уверен, что пропорция сохранится. Если бинарник будет размером 20 мб, подозреваю что разница останется в те же 5 мб. Это прекрасное решение когда проект имеет микроядро и over 9000 всяких мелких плагинов в dll/so.
Как академический эксперимент - круто, но вряд ли пригодится на практике.
ger0strat
новенький
 
Сообщения: 40
Зарегистрирован: 13.05.2014 19:35:56


Вернуться в Общее

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3

Рейтинг@Mail.ru