2024-12-20

vak: (Default)
Взялся я поисследовать Си-шный рантайм. Глянуть, что делается в программе до main() и после. Беру пустую программу:
$ cat empty.c 
int main()
{
// empty
}
Компилирую, причём линкую статически, чтобы избежать сложностей динамического загрузчика:
$ cc -static -Os empty.c -o empty
Глянем размер бинарника. На процессоре x86_64 под Ubuntu получается 667 килобайт:
$ size empty
text data bss dec hex filename
667574 23384 22440 713398 ae2b6 empty
На процессоре arm64 выходит чуть получше, 497 килобайт:
$ size empty
text data bss dec hex filename
497904 22180 21616 541700 84404 empty
Такие объёмы настораживают. Хорошо, запустим и посчитаем количество выполненных машинных команд. На процессоре x86_64:
$ bintrace -o x86.trace ./empty
$ grep '^0x' x86.trace | wc
170979 1371361 10303769
На процессоре arm64:
$ bintrace -o arm64.trace ./empty
$ grep '^0x' arm64.trace | wc
108719 565684 5186654
Ну офигеть просто. Больше ста тысяч команд чтобы просто стартонуть Си-шный код. Неладно что-то в Датском королевстве.

У меня иногда мелькает вопрос, чем занимаются компьютеры, когда мы на них не глядим. Какие-то бесполезные биты на байты множат. 😀
vak: (Default)
Взял пустую Си-шную программу "int main() {}". Скомпилировал статически под Линуксом. Прогнал через valgrind, получил профиль выполнения. Отрисовал граф вызовов с помощью qcachegrind.
gcc -g -Os -static empty.c -o empty
valgrind --tool=callgrind --dump-instr=yes --collect-jumps=yes ./empty
qcachegrind callgrind.out.*
Вот как эта халабуда выглядит.



Какие-то непонятные tunables сжирают время, и get_cie_encoding неясно что такое.

Под FreeBSD картина несколько яснее. И эффективнее: BSD-шная библиотека за 75471 процессорных инструкций супротив 170979 в Линуксе. Это на архитектуре x86_64.

vak: (Daemon)
Хотите вспомнить молодость? Запустить FreeBSD 1.0, историческую версию 1993 года. Или FreeBSD 2.0.5, версию 1995 года. Нынче это легко делается с помощью современного симулятора QEMU. Он ставится на Ubuntu командой "sudo apt install qemu-system-x86", а на маке "brew install qemu".

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

FreeBSD 1.0

Скачиваем файл FreeBSD-1.0-qemu.tar.xz. Извлекаем файлы, запускаем:
qemu-system-i386 \
-cpu 486 \
-m 64M \
-rtc base=localtime \
-hda freebsd1.0.qcow \
-netdev user,id=ed1,ipv6=off,hostfwd=tcp::2222-:22 \
-device ne2k_isa,netdev=ed1,mac=00:00:0d:31:04:11,irq=5
Входим как root, без пароля. Смотрим версию ядра, размеры файловых систем, версию компилятора. Останавливается машина командой halt.

FreeBSD 2.0.5

Именно на этой версии большинство народа из моего поколения получало первый юниксный опыт. Скачиваем файл FreeBSD-2.0.5-qemu.tar.xz. Здесь я сделал сразу четыре диска, хотя наполнен только один. Можете размечать их, монтировать и использовать под свои дела.
qemu-system-i386 \
-cpu pentium \
-m 128M \
-rtc base=localtime \
-hda freebsd2.0.5.qcow \
-hdb hdb.qcow \
-hdc hdc.qcow \
-hdd hdd.qcow \
-netdev user,id=ed1,ipv6=off,hostfwd=tcp::2222-:22 \
-device ne2k_isa,netdev=ed1,mac=00:00:0d:31:04:11,irq=5

Сеть настроена. Можете вспоминать, как и откуда скачивать пакеты по FTP и как их устанавливать. 😀

[personal profile] dmarck, заметь: ни тебе rtld, ни ASLR.