#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 почему-то очень много выделяет адресного пространства.
Обнаружил, что у меня стали иногда падать сборки 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.
Давеча писал про свой дефолтный аллокатор, и про то, что это, во многом, эмоциональное решение.
Короче, я привел свои эмоции в соответствие реальности, и перешел на 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.
GitHub
support another build system · Issue #126 · google/tcmalloc
Please, please support anything but bazel. bazel is very uncommon, huge, and depends on java. Having java in build toolchain is not always possible. (this is off-topic, but I can not really underst...
👍8🤯2❤1
Segment@tion fault
Внезапно перевел все наши продукты с jemalloc на mimalloc. Битва аллокаторов - вечный холивар, расскажу свои соображения, а вы добавьте в комментариях. - Причина, почему я вообще дернулся в смену аллокатора - клиенты начали ставить новый Raspbian, а там…
#tcmalloc пижже - https://t.iss.one/itpgchannel/369
(fun fact - так же является аллокатором по умолчанию в двух больших поисковых компаниях!)
Но в выборе между jemalloc и mimalloc, конечно, побеждает mimalloc.
(fun fact - так же является аллокатором по умолчанию в двух больших поисковых компаниях!)
Но в выборе между jemalloc и mimalloc, конечно, побеждает mimalloc.
Telegram
commit -m "better"
#allocator #tcmalloc #mimalloc
Давеча писал про свой дефолтный аллокатор, и про то, что это, во многом, эмоциональное решение.
Короче, я привел свои эмоции в соответствие реальности, и перешел на tcmalloc по дефолту.
* https://git.sr.ht/~pg/mix/tree/m…
Давеча писал про свой дефолтный аллокатор, и про то, что это, во многом, эмоциональное решение.
Короче, я привел свои эмоции в соответствие реальности, и перешел на tcmalloc по дефолту.
* https://git.sr.ht/~pg/mix/tree/m…
👍9😁5🤡2🆒1