commit -m "better"
2.96K subscribers
868 photos
105 videos
3 files
2.07K links
just random thoughts
Download Telegram
#tcmalloc #mimalloc #allocator

Обнаружил, что у меня стали иногда падать сборки webkit, по нехватке памяти.

Я как-то уже писал, что включил себе zswap на несколько гигабайт, ровно по этой же причине - в моменте там есть пара файлов, на которых у меня система упирается в лимит по памяти.

Странно, что оно начало случаться снова.

В барабашек я не верю, полез разбираться.

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

Дуровцы собирают телегу с jmalloc, я собираю весь дистрибутив с mimalloc.

Тут будет небольшое лирическое отступление.

Я фанат mimalloc. Мне он очень нравится идейно, я даже статью прочел. Хорошо знаю его кодовую базу.

Но, если честно, собирать целый дистрибутив на mimalloc - это, во многом, эмоциональное решение.

Потому что в качестве аллокатора по умолчанию я всем рекомендую tcmalloc, из gperftools.

Почему?

* жОпыт. Мой говорит, что tcmalloc - наиболее предсказуемый из всех известных мне аллокаторов. Да, он почти во всех сценариях уступает локальному лидеру, но, зато, никогда не приходит хуже, чем вторым. Предсказуемость - это очень важно.

* Известно довольно много случаев, когда в Я переходили на tcmalloc там, где важны latency spike.

* Я очень верю в hard work :) tcmalloc - это прямо очень hard work, туда вбуханы, не знаю, сотня человеко-лет. За это время инженеры гугла успели идентифицировать и починить кучу corner case, от которых страдают те или иные аллокаторы. Красивой идеей можно обогнать hard work в некоторых случаях, но не в среднем.

Поэтому, если есть время на тесты, я советую взять mimalloc, tcmalloc, и hualloc, и прогнать их на реальной нагрузке, а если нет - то tcmalloc как аллокатор по умолчанию.

Я решил посмотреть, как ведет себя сборка tdesktop с разными аллокаторами.

setup у меня примерно такой - собираю испытуемую программу с нужным аллокатором, запускаю ее, и начинаю серфить. В соседней консоли - top, по нему я в realtime слежу за RSS. CPU и прочее не смотрю, не интересно.

Графиков я не строил, все же, не новую конфигурацию железа для ДЦ выбираю.

Победил tcmalloc:

* В steady режиме процентов на 15 меньше RSS.

* В пиках потребления он лучше конкурентов в 1.5 раза.

Из интересного:

* tcmalloc потрясающе бережно относится к вирутальной памяти - он распределяет где-то 80% от аллоцированного адресного пространства. jemalloc - 50%(это довольно примерные цифры, скачет же все), mimalloc - 15%. В целом, кажется(я пока себя не до конца в этом убедил), это должно в лучшую сторону влиять на спайки, потому что чаще выдаем уже прогретую память.

* jemalloc - какая-то непредсказуемая хрень, то у нее потребление памяти скакануло высоко, то вообще все, досуха, вернули в систему.

* mimalloc, jemalloc примерно одинаково жрут памяти в среднем, и в пиках.

* mimalloc почему-то очень много выделяет адресного пространства.
🔥12👍7
#allocator #tcmalloc #mimalloc

Давеча писал про свой дефолтный аллокатор, и про то, что это, во многом, эмоциональное решение.

Короче, я привел свои эмоции в соответствие реальности, и перешел на tcmalloc по дефолту.

* https://git.sr.ht/~pg/mix/tree/main/item/pkgs/lib/c/alloc/ix.sh#L5 - по сути, это изменение 1 строчки кода, после чего весь репозиторий будет линковаться с tcmalloc, если не указано обратное

* конечно, реальное изменение было несколько больше, потому что, я напомню, цепочка #bootstrap у меня теперь строится автоматически, и теперь tcmalloc может использоваться раньше в этой цепочке, когда мой инструментарий был недостаточен, чтобы собрать его полную версию. Самое простое - не готов perl, для запуска GNU autohell скриптов. Поэтому я взял более свежую версию gperftools, где есть поддержка cmake. Сборка cmake там пока молодая, немного кривая, за ней приходится подрихтовывать сборочные артефакты руками - https://git.sr.ht/~pg/mix/tree/main/item/pkgs/lib/tcmalloc/cmake/ix.sh#L52

(кстати, пользуясь случаем - полайкайте, чтоли, https://github.com/google/tcmalloc/issues/126 - прошу G-word company, чтобы они поддержали сборку каноничного tcmalloc без Bazel)

* Число пересборок библиотек стало меньше. Потому что раньше я принудительно собирал некоторые гуевые приложения с tcmalloc, а остальные - с mimalloc, а сейчас все получается с tcmalloc. Поэтому всякие mesa + gtk + qt раньше собирались по 2 раза, а теперь 1.

* у tcmalloc очень большой footprint - размер на диске 600Kb. 400Kb сам tcmalloc + 200Kb c++ runtime. Это довольно дофига, сильно вырос объем дискового пространства, занимаемого базовыми утилитами OS.

Я, наконец-то, нашел время это все подрихтовать, теперь базовые утилиты собираются с другим набором флагов - https://git.sr.ht/~pg/mix/tree/main/item/pkgs/set/system/0/ix.sh#L4 :

* curses=netbsd говорит нам, что не нужно использовать ncurses для этих утилит. На минус куча лишних terminfo в базовом образе.

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

* purec=musl/unwrap говорит нам, что мы используем libc musl без переопределения аллокатора. Встроенный в musl аллокатор как раз хорош для такого рода использования.

Ну и, раз я уж этим занялся, то я аккуратно:

* почикал из системных пакетов неиспользуемые тулзы. Например, https://git.sr.ht/~pg/mix/tree/main/item/pkgs/bin/dbus/sys/ix.sh#L5 - Действительно, зачем в системном пакете что-то, отличное от dbus-daemon? Клиента, если надо, пользователь поставит в свой #realm.

* Редко запускаемые, one-shot программы пожал с помощью upx. busybox не пожал, нефиг разжимать при каждом запуске cp/rm/mv/etc. Демоны тоже жать не стал, им нужен backing store за замапленной программой в памяти. https://git.sr.ht/~pg/mix/tree/main/item/pkgs/bin/iwd/sys/ix.sh#L12 Кстати, fun fact - upx почти не имеет смысла с динамической линковкой, но хорошо помогает в случае статической. В копилку примеров решений, которые по разному работают в разных мирах.

После всех этих действий объем базового #realm упал с 40 мегабайт до 17 - https://pastebin.com/raw/6b9Xtg5n (причем 7Mb из них - сжатая в 1 файл питонячка бинаря ix - graph executor моего пакетного менеджера, который надо переписать на С++/Rust).

Напомню, что мой базовый #realm позволяет поднять OS с настроенной сетью и серверной частью seat/input/sound/etc.
👍8🤯21