#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
Хорошие измерения - сложно.
В комментариях к моему вчерашнему посту мне объяснили, что коллеги выбрали jemalloc после тестов на особо всратом канале, где зашкаливало потребление памяти. Канал можно подсмотреть в дискуссии.
Мне стало интересно, как это починить для #tcmalloc, и я решил запустить background thread, который бы постепенно возвращал память в систему.
Вот мой код. https://git.sr.ht/~pg/mix/tree/main/item/pkgs/lib/tcmalloc/trim/mix.sh
(тут хочу отдельно отметить, какая у меня крутая система сборки - кодогенерация исходников на С++, с настройками от потребителя через флажки - https://git.sr.ht/~pg/mix/tree/main/item/pkgs/bin/telegram/desktop/unwrap/mix.sh#L38 - тут написано, что мы используем такую библиотеку, которая бы освобождала по 10 мегабайт в секунду. Мне, признаться, даже немного стремно выпускать такую описательную мощь наружу)
Все работало очень хорошо, при выбранных мной параметрах телега возвращалась в steady режим за пару минут, этот режим был лучше того, что показывал jemalloc.
И я уже предвкушал момент, когда я напишу что-нить типа "ну, вот так-то и так-то, а если надо еще, то пусть коллеги приходят за небольшой прайс за консультацией".
Но не тут-то было, и в комментариях мне рассказали, что телега, в случае сборки по феншую, каноничными скриптами, активирует похожий режим, только для jemalloc. https://github.com/desktop-app/cmake_helpers/blob/87d46d81111d9ebfff560e1be3d52306c7475fe7/linux_jemalloc_helper/linux_jemalloc_helper.cpp
Починил, провел новые измерения, и имею сказать:
* В пике RSS у tcmalloc и jemalloc при просмотре этого канала примерно одинаковый - 4 гига.
* После возвращения в steady режим жрут они по 450 - 500 мегабайт, тоже одинаково.
* В steady режим jemalloc возвращается быстрее, но это мой личный выбор, потому что вернуть много памяти сразу - это долго, и может быть заметно в виде latency spike.
* Для mimalloc я такого режима не нашел, для него результатов не будет.
Короче, jemalloc для телеги тоже норм, но я доверюсь своему личному жОпыту.
Хочу попробовать воткнуть такое в другие программы, которые в пиках могут жрать много памяти - в worker браузера, etc.
Так же мне стало интересно, как дела обстоят с телегами, которые собирают дистрибутивы - все ли там хорошо, или нет.
* Alpine linux - https://git.alpinelinux.org/aports/tree/community/telegram-desktop/disable-jemalloc.patch они явно отключают jemalloc в пользу системного. Скорее всего, там все плохо, и телега жрет памяти, как не в себя.
* Arch linux - https://archlinux.org/packages/community/x86_64/telegram-desktop/ https://github.com/archlinux/svntogit-community/blob/packages/telegram-desktop/trunk/PKGBUILD - все сложно. Есть зависимость от системного jemalloc, но забандленый явно не выключен. Поэтому все зависит от того, как работает configure/cmake(выключит он или нет забандленый код, если найдет системный), а дальше - от порядка линковки и фичей системного jemalloc. Пара вариантов:
1. Все работает just as planned, используется забандленный, линкер просто выкидывает зависимость от системного.
2. Все работает наперекосяк. Самыми разными способами. Например, символы аллокатора берутся из системного, заголовки - из забандленного, код по активации вызывается или нет, ну и в системном может просто не быть поддержки этого вызова.
Нужно брать и проверять наживую, фанатам того или иного дистра рекомендую проверить телегу в нем - поставить gdb на mallctl, и потрейсить готовые бинари.
В комментариях к моему вчерашнему посту мне объяснили, что коллеги выбрали jemalloc после тестов на особо всратом канале, где зашкаливало потребление памяти. Канал можно подсмотреть в дискуссии.
Мне стало интересно, как это починить для #tcmalloc, и я решил запустить background thread, который бы постепенно возвращал память в систему.
Вот мой код. https://git.sr.ht/~pg/mix/tree/main/item/pkgs/lib/tcmalloc/trim/mix.sh
(тут хочу отдельно отметить, какая у меня крутая система сборки - кодогенерация исходников на С++, с настройками от потребителя через флажки - https://git.sr.ht/~pg/mix/tree/main/item/pkgs/bin/telegram/desktop/unwrap/mix.sh#L38 - тут написано, что мы используем такую библиотеку, которая бы освобождала по 10 мегабайт в секунду. Мне, признаться, даже немного стремно выпускать такую описательную мощь наружу)
Все работало очень хорошо, при выбранных мной параметрах телега возвращалась в steady режим за пару минут, этот режим был лучше того, что показывал jemalloc.
И я уже предвкушал момент, когда я напишу что-нить типа "ну, вот так-то и так-то, а если надо еще, то пусть коллеги приходят за небольшой прайс за консультацией".
Но не тут-то было, и в комментариях мне рассказали, что телега, в случае сборки по феншую, каноничными скриптами, активирует похожий режим, только для jemalloc. https://github.com/desktop-app/cmake_helpers/blob/87d46d81111d9ebfff560e1be3d52306c7475fe7/linux_jemalloc_helper/linux_jemalloc_helper.cpp
Починил, провел новые измерения, и имею сказать:
* В пике RSS у tcmalloc и jemalloc при просмотре этого канала примерно одинаковый - 4 гига.
* После возвращения в steady режим жрут они по 450 - 500 мегабайт, тоже одинаково.
* В steady режим jemalloc возвращается быстрее, но это мой личный выбор, потому что вернуть много памяти сразу - это долго, и может быть заметно в виде latency spike.
* Для mimalloc я такого режима не нашел, для него результатов не будет.
Короче, jemalloc для телеги тоже норм, но я доверюсь своему личному жОпыту.
Хочу попробовать воткнуть такое в другие программы, которые в пиках могут жрать много памяти - в worker браузера, etc.
Так же мне стало интересно, как дела обстоят с телегами, которые собирают дистрибутивы - все ли там хорошо, или нет.
* Alpine linux - https://git.alpinelinux.org/aports/tree/community/telegram-desktop/disable-jemalloc.patch они явно отключают jemalloc в пользу системного. Скорее всего, там все плохо, и телега жрет памяти, как не в себя.
* Arch linux - https://archlinux.org/packages/community/x86_64/telegram-desktop/ https://github.com/archlinux/svntogit-community/blob/packages/telegram-desktop/trunk/PKGBUILD - все сложно. Есть зависимость от системного jemalloc, но забандленый явно не выключен. Поэтому все зависит от того, как работает configure/cmake(выключит он или нет забандленый код, если найдет системный), а дальше - от порядка линковки и фичей системного jemalloc. Пара вариантов:
1. Все работает just as planned, используется забандленный, линкер просто выкидывает зависимость от системного.
2. Все работает наперекосяк. Самыми разными способами. Например, символы аллокатора берутся из системного, заголовки - из забандленного, код по активации вызывается или нет, ну и в системном может просто не быть поддержки этого вызова.
Нужно брать и проверять наживую, фанатам того или иного дистра рекомендую проверить телегу в нем - поставить gdb на mallctl, и потрейсить готовые бинари.
🔥9👍1😁1
У меня сегодня 2 истории, несколько технические, но, КМК, интересные.
В #tcmalloc нет реализации reallocarray(). В принципе, они в своем праве, потому что никому ничего не должны.
Проблема в том, что в musl reallocarray реализован.
Почему это проблема? Потому что у нас получается интересная ситуация - в stdlib.h есть сигнатура для reallocarray(), а в libmusl.a + libtcmalloc.a такого символа нет.
Дальше получается следующее:
1) Если configure проекта определяет наличие символа через компиляцию, то он получит, что reallocarray есть в наличии, и не включит у себя флажок, по которому бы код подставил свою реализацию. И в момент линковки будет ошибка.
2) Если configure определяет это через линковку, то он получит, что reallocarray нет, и включит флажок, по которому код включит у себя fallback на свою реализацию. Казалось бы, все хорошо? Нет, потому что эта рализация может не скомпилироваться, потому что в stdlib.h есть сигнатура от musl, и они могут, в деталях, не совпадать(например, throw()/noexept/etc).
Засада.
После ряда попыток это workaround в разных местах, я решил, что проще всего добавить реализацию в tcmalloc:
https://git.sr.ht/~pg/mix/tree/main/item/pkgs/lib/tcmalloc/mix.sh#L25
Кстати, в реализации, в которой я на это наткнулся, ошибка - https://git.sr.ht/~emersion/basu/tree/master/item/src/basic/alloc-util.h#L76 (впрочем, AFAIK стандарта на это еще нет, поэтому все в своем праве)
———
Решил я себе собрать #dosbox.
А он, зараза, зависит от SDL1, которая давно не обновляется, и собирать ее с wayland мне особо не хотелось.
Есть реализация api sdl1 через sdl2. https://github.com/libsdl-org/sdl12-compat/blob/main/src/SDL12_compat.c (в одном файле, да)
От автора sdl, судя по всему, он ее делал за деньги(потому что такое говно, как по этой ссылке, можно пилить только за деньги, и очень большие), работает хорошо.
Проблема в том, что у sdl1 и sdl2 один и тот же namespace, и функции пересекаются по именам. Поэтому коллега, ничтоже сумняшеся, загружает .so с SDL2 в RTLD_LOCAL режиме, и достает оттуда символы почем зря.
Мне пришлось соорудить интересную шутку - собрать библиотеку SDL2, и переложить все символы в другой namespace(по сути, добавить префикс V2_ ко всем экспортируемым именам). Я назвал библиотеку "SDL2 chimera". https://git.sr.ht/~pg/mix/tree/main/item/pkgs/lib/sdl/chimera/mix.sh#L12 После чего "загрузка" такой .a библиотеки дело техники - нужно всего лишь составить список вида [("SDL2", "SDL_xxx", &V2_SDL_xxx)] для моего загрузчика .so. https://git.sr.ht/~pg/mix/tree/main/item/pkgs/lib/sdl/chimera/dl/mix.sh#L14 Пересечений с SDL1 в общем пространстве имен бинарника не будет.
dosbox, сликованный в один бинарь с SDL2 - никто не умеет, а я умею :)
Отмечу, что вот это решение - оно вполне себе норм, то есть, это не хак, который будет разваливаться от каждого чиха. Переименование символов - хорошо определенная операция на объектных файлах, без странных side effect. Ну а добавить "V2_" - это очень разумная эмуляция для RTLD_LOCAL, найдите 5 отличий, что называется.
В #tcmalloc нет реализации reallocarray(). В принципе, они в своем праве, потому что никому ничего не должны.
Проблема в том, что в musl reallocarray реализован.
Почему это проблема? Потому что у нас получается интересная ситуация - в stdlib.h есть сигнатура для reallocarray(), а в libmusl.a + libtcmalloc.a такого символа нет.
Дальше получается следующее:
1) Если configure проекта определяет наличие символа через компиляцию, то он получит, что reallocarray есть в наличии, и не включит у себя флажок, по которому бы код подставил свою реализацию. И в момент линковки будет ошибка.
2) Если configure определяет это через линковку, то он получит, что reallocarray нет, и включит флажок, по которому код включит у себя fallback на свою реализацию. Казалось бы, все хорошо? Нет, потому что эта рализация может не скомпилироваться, потому что в stdlib.h есть сигнатура от musl, и они могут, в деталях, не совпадать(например, throw()/noexept/etc).
Засада.
После ряда попыток это workaround в разных местах, я решил, что проще всего добавить реализацию в tcmalloc:
https://git.sr.ht/~pg/mix/tree/main/item/pkgs/lib/tcmalloc/mix.sh#L25
Кстати, в реализации, в которой я на это наткнулся, ошибка - https://git.sr.ht/~emersion/basu/tree/master/item/src/basic/alloc-util.h#L76 (впрочем, AFAIK стандарта на это еще нет, поэтому все в своем праве)
———
Решил я себе собрать #dosbox.
А он, зараза, зависит от SDL1, которая давно не обновляется, и собирать ее с wayland мне особо не хотелось.
Есть реализация api sdl1 через sdl2. https://github.com/libsdl-org/sdl12-compat/blob/main/src/SDL12_compat.c (в одном файле, да)
От автора sdl, судя по всему, он ее делал за деньги(потому что такое говно, как по этой ссылке, можно пилить только за деньги, и очень большие), работает хорошо.
Проблема в том, что у sdl1 и sdl2 один и тот же namespace, и функции пересекаются по именам. Поэтому коллега, ничтоже сумняшеся, загружает .so с SDL2 в RTLD_LOCAL режиме, и достает оттуда символы почем зря.
Мне пришлось соорудить интересную шутку - собрать библиотеку SDL2, и переложить все символы в другой namespace(по сути, добавить префикс V2_ ко всем экспортируемым именам). Я назвал библиотеку "SDL2 chimera". https://git.sr.ht/~pg/mix/tree/main/item/pkgs/lib/sdl/chimera/mix.sh#L12 После чего "загрузка" такой .a библиотеки дело техники - нужно всего лишь составить список вида [("SDL2", "SDL_xxx", &V2_SDL_xxx)] для моего загрузчика .so. https://git.sr.ht/~pg/mix/tree/main/item/pkgs/lib/sdl/chimera/dl/mix.sh#L14 Пересечений с SDL1 в общем пространстве имен бинарника не будет.
dosbox, сликованный в один бинарь с SDL2 - никто не умеет, а я умею :)
Отмечу, что вот это решение - оно вполне себе норм, то есть, это не хак, который будет разваливаться от каждого чиха. Переименование символов - хорошо определенная операция на объектных файлах, без странных side effect. Ну а добавить "V2_" - это очень разумная эмуляция для RTLD_LOCAL, найдите 5 отличий, что называется.
👍10🔥5
#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
commit -m "better"
В батле "статическая vs. динамическая линковка" есть один фактор, про который особо никто не рассказывает, ну или мне просто не встречалось раньше. Это эстетика! Причем не простая эстетика, что, дескать, в случае статической линковки по всей fs не валяются…
#gold
Обещал пример разделения статических библиотек, которое никогда бы не смогло случиться во внешнем мире с .so
Как я уже рассказывал, у меня есть реализация функций backtrace(), на самом деле, их там ажно три штуки:
https://github.com/pg83/ix/tree/main/pkgs/lib/execinfo - у меня лежит 4 их реализации:
1) https://github.com/pg83/ix/tree/main/pkgs/lib/execinfo/fake
Это просто реализация, которая ничего не делает(имеет право!), с которой как раз и сломался eternal terminal #et
2) https://github.com/pg83/ix/tree/main/pkgs/lib/execinfo/fp
Это реализация, цельнотянутая из BSD мира, https://www.freshports.org/devel/libexecinfo, широко известна в узких кругах non-glibc linux.
Она содержит фатальный недостаток - если ее позвать из кода, который на x86_64 скомпилен с флагами компилятора по умолчанию(без -fno-omit-frame-pointer), она приводит к падению программы, потому что она падает без frame pointer.
3) https://github.com/pg83/ix/tree/main/pkgs/lib/execinfo/itanium
Эту реализацию наговнокодил я сам, поверх itanium abi для раскрутки стека. Он всегда доступен в программах на C++, а у меня используется #tcmalloc, поэтому по коду это для меня бесплатно. Собственно, она у меня стоит по умолчанию, с возможностью переопределения - https://github.com/pg83/ix/blob/main/pkgs/lib/execinfo/ix.sh Это полезно в цепочке bootstrap, чтобы для первого компилятора собирать поменьше кода - https://github.com/pg83/ix/blob/main/pkgs/bld/boot/8/clang/base/ix.sh
4) https://github.com/pg83/ix/tree/main/pkgs/lib/execinfo/unwind
И реализация поверх библиотеки libunwind от HP. Это старая, известная, библиотека, одна из трех более-менее известных реализаций itanium abi(наряду с stdc++ от gnu, и libunwind от проекта llvm)
Тут очень важно отметить, что, в двух последних случаях я реализовал только функцию backtrace(), одну из трех нужных. Потому что я ленивая жопа, да.
Что бы я сделал, если бы делал .so для внешнего мира? Я бы скопировал две оставшиеся функции из пункта 2) к себе в проект, и был бы счастлив.
Но, в случае статической линковки я могу себе позволить иметь сколько угодно артефактов любой степени всратости, лишь бы конечный продукт работал.
Поэтому я делаю финт ушами - https://github.com/pg83/ix/blob/main/pkgs/lib/execinfo/format/ix.sh
Я пересобираю библиотеку из пункта 2, но с указанием, что в .a файле нужно переименовать функцию backtrace(). На выходе я имею библиотеку, в которой есть функции xxx_backtrace(), backtrace_symbols(), и backtrace_symbols_fd()
Если ее скомпоновать с библиотекой 3), или библиотекой 4), то я получу на выходе годный артефакт. Линкер же выкинет при линковке ненужную функцию xxx_backtrace(), и все будет по красоте!
https://github.com/pg83/ix/blob/main/pkgs/lib/execinfo/itanium/ix.sh#L6
https://github.com/pg83/ix/blob/main/pkgs/lib/execinfo/unwind/ix.sh#L6
Собственно, я так и делаю.
В мире динамической линковки это было бы весьма странно.
В случае же статической сборки, если не особенно сильно принюхиваться, то норм, ну и я, заодно, сэкономил себе кучу времени и усилий.
Обещал пример разделения статических библиотек, которое никогда бы не смогло случиться во внешнем мире с .so
Как я уже рассказывал, у меня есть реализация функций backtrace(), на самом деле, их там ажно три штуки:
#include <execinfo.h>
int backtrace(void **buffer, int size);
char **backtrace_symbols(void *const *
buffer, int size);
void backtrace_symbols_fd(void *const *
buffer, int size, int fd);
https://github.com/pg83/ix/tree/main/pkgs/lib/execinfo - у меня лежит 4 их реализации:
1) https://github.com/pg83/ix/tree/main/pkgs/lib/execinfo/fake
Это просто реализация, которая ничего не делает(имеет право!), с которой как раз и сломался eternal terminal #et
2) https://github.com/pg83/ix/tree/main/pkgs/lib/execinfo/fp
Это реализация, цельнотянутая из BSD мира, https://www.freshports.org/devel/libexecinfo, широко известна в узких кругах non-glibc linux.
Она содержит фатальный недостаток - если ее позвать из кода, который на x86_64 скомпилен с флагами компилятора по умолчанию(без -fno-omit-frame-pointer), она приводит к падению программы, потому что она падает без frame pointer.
3) https://github.com/pg83/ix/tree/main/pkgs/lib/execinfo/itanium
Эту реализацию наговнокодил я сам, поверх itanium abi для раскрутки стека. Он всегда доступен в программах на C++, а у меня используется #tcmalloc, поэтому по коду это для меня бесплатно. Собственно, она у меня стоит по умолчанию, с возможностью переопределения - https://github.com/pg83/ix/blob/main/pkgs/lib/execinfo/ix.sh Это полезно в цепочке bootstrap, чтобы для первого компилятора собирать поменьше кода - https://github.com/pg83/ix/blob/main/pkgs/bld/boot/8/clang/base/ix.sh
4) https://github.com/pg83/ix/tree/main/pkgs/lib/execinfo/unwind
И реализация поверх библиотеки libunwind от HP. Это старая, известная, библиотека, одна из трех более-менее известных реализаций itanium abi(наряду с stdc++ от gnu, и libunwind от проекта llvm)
Тут очень важно отметить, что, в двух последних случаях я реализовал только функцию backtrace(), одну из трех нужных. Потому что я ленивая жопа, да.
Что бы я сделал, если бы делал .so для внешнего мира? Я бы скопировал две оставшиеся функции из пункта 2) к себе в проект, и был бы счастлив.
Но, в случае статической линковки я могу себе позволить иметь сколько угодно артефактов любой степени всратости, лишь бы конечный продукт работал.
Поэтому я делаю финт ушами - https://github.com/pg83/ix/blob/main/pkgs/lib/execinfo/format/ix.sh
Я пересобираю библиотеку из пункта 2, но с указанием, что в .a файле нужно переименовать функцию backtrace(). На выходе я имею библиотеку, в которой есть функции xxx_backtrace(), backtrace_symbols(), и backtrace_symbols_fd()
Если ее скомпоновать с библиотекой 3), или библиотекой 4), то я получу на выходе годный артефакт. Линкер же выкинет при линковке ненужную функцию xxx_backtrace(), и все будет по красоте!
https://github.com/pg83/ix/blob/main/pkgs/lib/execinfo/itanium/ix.sh#L6
https://github.com/pg83/ix/blob/main/pkgs/lib/execinfo/unwind/ix.sh#L6
Собственно, я так и делаю.
В мире динамической линковки это было бы весьма странно.
В случае же статической сборки, если не особенно сильно принюхиваться, то норм, ну и я, заодно, сэкономил себе кучу времени и усилий.
GitHub
ix/pkgs/lib/execinfo at main · pg83/ix
ix package manager. Contribute to pg83/ix development by creating an account on GitHub.
👍8🤔4🔥3
Будни #bootstrap
Вышла новая тележенька, обновился сразу на 4.12.2.
Не знаю, чего там нового, все собралось без новых патчей, но, что интересно, коллеги перешли на scudo - https://github.com/desktop-app/cmake_helpers/tree/92f27add11ae4280939079249d0f9da933ece6ad/external/scudo https://llvm.org/docs/ScudoHardenedAllocator.html
Это такой hardened allocator, раньше развивался в составе Android, потом перешел под крыло LLVM.
Интересно, зачем.
В прошлом тележенька оптимизировала memory pressure, и им было важно, чтобы память, после пиков потребления, быстро возвращалась в систему.
Я, когда подбирал аллокатор для тележеньки, остановился на #tcmalloc, потому что, хоть он и чуть медленнее возвращал память в систему, то общий memory footprint у него был лучше.
Scudo я тоже тестировал, ничем интересным он тогда себя не проявил.
Полагаю, что коллег задолбало искать проезды в проде, и вот, отсюда scudo.
Вышла новая тележенька, обновился сразу на 4.12.2.
Не знаю, чего там нового, все собралось без новых патчей, но, что интересно, коллеги перешли на scudo - https://github.com/desktop-app/cmake_helpers/tree/92f27add11ae4280939079249d0f9da933ece6ad/external/scudo https://llvm.org/docs/ScudoHardenedAllocator.html
Это такой hardened allocator, раньше развивался в составе Android, потом перешел под крыло LLVM.
Интересно, зачем.
В прошлом тележенька оптимизировала memory pressure, и им было важно, чтобы память, после пиков потребления, быстро возвращалась в систему.
Я, когда подбирал аллокатор для тележеньки, остановился на #tcmalloc, потому что, хоть он и чуть медленнее возвращал память в систему, то общий memory footprint у него был лучше.
Scudo я тоже тестировал, ничем интересным он тогда себя не проявил.
Полагаю, что коллег задолбало искать проезды в проде, и вот, отсюда scudo.
GitHub
cmake_helpers/external/scudo at 92f27add11ae4280939079249d0f9da933ece6ad · desktop-app/cmake_helpers
CMake helper scripts. Contribute to desktop-app/cmake_helpers development by creating an account on GitHub.
🔥4👍3❤2🤔1
commit -m "better"
#vendor Сегодня про еще один механизм де-вендоринга, который я называю "кузькина мать". https://github.com/pg83/ix/blob/main/pkgs/bld/devendor/devendor.sh Этот скрипт я применяю, когда авторы кода не предусмотрели никакой возможности отключить завендоренную…
#vendor
Пришлось на днях снова применить "кузькину мать".
На этот раз по тележеньке - https://github.com/pg83/ix/commit/d64dfd7a674571ee331df253942cef270851f72e
Потому что эти господа, видимо, наслаждаются своей ересью в виде scudo allocator (https://t.iss.one/itpgchannel/1494). А мне мил мой #tcmalloc (https://t.iss.one/itpgchannel/328), потому что с ним памяти жреть меньше, и скроллинг плавнее.
У меня со scudo allocator тоже собрана пара программ, типа ssh server, который я использую для эскалации привилегий в системе, там это оправдано.
Так как конечный продукт, в итоге, собираю я, то я и навязал свою точку зрения в виде tcmalloc.
Пришлось на днях снова применить "кузькину мать".
На этот раз по тележеньке - https://github.com/pg83/ix/commit/d64dfd7a674571ee331df253942cef270851f72e
Потому что эти господа, видимо, наслаждаются своей ересью в виде scudo allocator (https://t.iss.one/itpgchannel/1494). А мне мил мой #tcmalloc (https://t.iss.one/itpgchannel/328), потому что с ним памяти жреть меньше, и скроллинг плавнее.
У меня со scudo allocator тоже собрана пара программ, типа ssh server, который я использую для эскалации привилегий в системе, там это оправдано.
Так как конечный продукт, в итоге, собираю я, то я и навязал свою точку зрения в виде tcmalloc.
GitHub
obey my rules · pg83/ix@d64dfd7
ix package manager. Contribute to pg83/ix development by creating an account on GitHub.
👍7❤5😁3
commit -m "better"
#vendor Пришлось на днях снова применить "кузькину мать". На этот раз по тележеньке - https://github.com/pg83/ix/commit/d64dfd7a674571ee331df253942cef270851f72e Потому что эти господа, видимо, наслаждаются своей ересью в виде scudo allocator (https://t…
#vendor
https://github.com/desktop-app/cmake_helpers/commit/5a19eddd4554486547d6d5dac3002a93bc105867
Тем временем, коллеги откатили scudo, и вернули jemalloc.
Верю, что пройдет еще пара итераций, и там таки окажется #tcmalloc, хехе.
Как я это заметил? Ну, у меня сломалась "кузькина мать", когда не смогла развендорить scudo в новой версии телеги.
UPD: у меня github показывает розовых поней, наверное, это как-то связано
https://github.com/desktop-app/cmake_helpers/commit/5a19eddd4554486547d6d5dac3002a93bc105867
Тем временем, коллеги откатили scudo, и вернули jemalloc.
Верю, что пройдет еще пара итераций, и там таки окажется #tcmalloc, хехе.
Как я это заметил? Ну, у меня сломалась "кузькина мать", когда не смогла развендорить scudo в новой версии телеги.
UPD: у меня github показывает розовых поней, наверное, это как-то связано
GitHub
Revert "Replace jemalloc with scudo" · desktop-app/cmake_helpers@5a19edd
This reverts commit c2ef75186a82ab89c6f742f6493def1a0d65ffdf.
😁6🤔4🥴2👍1🔥1
commit -m "better"
#llvmweekly https://devblogs.microsoft.com/oldnewthing/20240510-00/?p=109742 Классный текст про устройство строки в 3 мажорных stl (clang, msvc, gcc). Все 3 - разные, с разными tradeoff, и с разными perf характеристиками а разных использованиях. В целом…
#llvmweekly
https://c3.handmade.network/blog/p/8852-how_bad_is_llvm_really
TL;DR - медленно, семантика промежуточного представления (над которым производятся оптимизации) заточены на С/С++, и сделать иначе - невозможно. Ну, например, деление на 0 в LLVM - UB, а какой-то "другой" язык хочет уметь это обрабатывать. В итоге, LLVM навязывает некоторую семантику любому языку, которые хочет его использовать. Например, бесконечный цикл в rust, который некорретно оптимизировался llvm - https://github.com/rust-lang/rust/issues/28728
Зато много готовых оптимизаций из коробки.
Так же автор (очень справедливо!) вопрошает, какого хрена в коде LLVM не используются арены и пулы, везде, налево, и направо, потому что основные причины тормозов LLVM - это деревянные структуры без data locality.
У автора замена аллокатора для LLVM на mimalloc дает хороший буст в скорости (+10%).
Я систематически бенчил clang с разными аллокаторами, и остановился на #tcmalloc от Google, по скорости тот же mim, но в пике жрет прямо существенно меньше памяти.
Неутешительный вывод такой - начинать разработку компилятора стоит с LLVM, а вот дальше есть варианты.
https://c3.handmade.network/blog/p/8852-how_bad_is_llvm_really
TL;DR - медленно, семантика промежуточного представления (над которым производятся оптимизации) заточены на С/С++, и сделать иначе - невозможно. Ну, например, деление на 0 в LLVM - UB, а какой-то "другой" язык хочет уметь это обрабатывать. В итоге, LLVM навязывает некоторую семантику любому языку, которые хочет его использовать. Например, бесконечный цикл в rust, который некорретно оптимизировался llvm - https://github.com/rust-lang/rust/issues/28728
Зато много готовых оптимизаций из коробки.
Так же автор (очень справедливо!) вопрошает, какого хрена в коде LLVM не используются арены и пулы, везде, налево, и направо, потому что основные причины тормозов LLVM - это деревянные структуры без data locality.
У автора замена аллокатора для LLVM на mimalloc дает хороший буст в скорости (+10%).
Я систематически бенчил clang с разными аллокаторами, и остановился на #tcmalloc от Google, по скорости тот же mim, но в пике жрет прямо существенно меньше памяти.
Неутешительный вывод такой - начинать разработку компилятора стоит с LLVM, а вот дальше есть варианты.
Handmade Network
How bad is LLVM really?
LLVM used to be hailed as a great thing, but with language projects such as Rust, Zig and others c…
👍18
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
commit -m "better"
пижже
Мне тут справедливо пишут, что тема "почему #tcmalloc пижже" не раскрыта.
Далее - мой личный OPS опыт, основанный на довольно больших prod backend, и на том, что весь мой дистрибутив Linux работает с tcmalloc.
Если взять N аллокаторов, и M бенчмарков/экспериментов в проде, то окажется, что:
* tcmalloc - почти всегда на втором месте (1)
* почти всегда есть аллокатор лучше, для заданного теста/бенчмарка
* у любого другого аллокатора будут очень плохие краевые случаи - когда он в бенчмарке оказывается на последнем месте
* нет аллокатора, который бы всегда был первым
Поэтому, если вы готовы инвестировать в регулярный переподбор аллокатора для своего приложения, то это вряд ли будет tcmalloc.
А если не готовы - то это sane default, потому что смотри пункт (1).
Дальше болтология.
Я, знаете ли, очень верю в hard work, и не очень верю в "классную идею, которая зарулит всех".
Google инвестировал, наверное, сотню человеко-лет в свой аллокатор, он собрал все грабли, и подпер их костыликом, этого ни у кого больше нет, отсюда и следует пункт (1), а это очень важно для sane default.
UPD: сслыка от наших радиослушателей - https://t.iss.one/psauxww/1345?comment=25405
Далее - мой личный OPS опыт, основанный на довольно больших prod backend, и на том, что весь мой дистрибутив Linux работает с tcmalloc.
Если взять N аллокаторов, и M бенчмарков/экспериментов в проде, то окажется, что:
* tcmalloc - почти всегда на втором месте (1)
* почти всегда есть аллокатор лучше, для заданного теста/бенчмарка
* у любого другого аллокатора будут очень плохие краевые случаи - когда он в бенчмарке оказывается на последнем месте
* нет аллокатора, который бы всегда был первым
Поэтому, если вы готовы инвестировать в регулярный переподбор аллокатора для своего приложения, то это вряд ли будет tcmalloc.
А если не готовы - то это sane default, потому что смотри пункт (1).
Дальше болтология.
Я, знаете ли, очень верю в hard work, и не очень верю в "классную идею, которая зарулит всех".
Google инвестировал, наверное, сотню человеко-лет в свой аллокатор, он собрал все грабли, и подпер их костыликом, этого ни у кого больше нет, отсюда и следует пункт (1), а это очень важно для sane default.
UPD: сслыка от наших радиослушателей - https://t.iss.one/psauxww/1345?comment=25405
Telegram
Loyd in E = mc² + AI
Поделюсь и своим опытом по теме современных аллокаторов.
Мы тоже используем mimalloc как дефолт. Но без secure, на некоторых бенчах сильно больше 10% может резать.
Однако лучшим general-purpose аллокатором я считаю гугловый tcmalloc у которого есть важная…
Мы тоже используем mimalloc как дефолт. Но без secure, на некоторых бенчах сильно больше 10% может резать.
Однако лучшим general-purpose аллокатором я считаю гугловый tcmalloc у которого есть важная…
👍19🔥6🆒4❤2
commit -m "better"
Мне тут справедливо пишут, что тема "почему #tcmalloc пижже" не раскрыта.
Вспомнил еще интересный аргумент про #tcmalloc.
Сначала - небольшое лирическое отступление.
В нашей корпоративной монорепе (цифры далее - это очень грубое приближение, надеюсь, я не сильно ошибся в порядках) - 10^5 модулей, 10^6 файлов, и 10^7 "запусков" (условно говоря, сборка объектника или запуск теста), которые мы гоняем в нашем CI, на каждый (!) PR, который идет в эту монорепу. Понятное дело, что там есть ранее отсечение - мы не пересобираем то, что заведомо не может поменяться в проверяемом PR.
Этим делом в полку загружено несколько тысяч вполне современных серверов.
При таких масштабах всякие проблемы, которые обычно незаметны, всплывают сразу.
Например, когда мы катим новый clang, то сразу натыкаемся на все багло, которое в него посадили, это сразу видно в CI. Кстати, именно поэтому мы всегда берем версию, которая последняя в своей стабильной ветке, нулевые и первые не берем.
К чему это я?
Когда-то, когда я менял предыдущий дефолт на #tcmalloc, я, для эксперимента, послал в наш CI 3 PR, в каждом из которых менял аллокатор по умолчанию на #tcmalloc, mimalloc, и что-то еще.
В случае tcmalloc PR был "почти зеленый", в остальных PR было прилично посыпавшихся тестов!
Вот, такая вот байка про качество кода tcmalloc.
Сначала - небольшое лирическое отступление.
В нашей корпоративной монорепе (цифры далее - это очень грубое приближение, надеюсь, я не сильно ошибся в порядках) - 10^5 модулей, 10^6 файлов, и 10^7 "запусков" (условно говоря, сборка объектника или запуск теста), которые мы гоняем в нашем CI, на каждый (!) PR, который идет в эту монорепу. Понятное дело, что там есть ранее отсечение - мы не пересобираем то, что заведомо не может поменяться в проверяемом PR.
Этим делом в полку загружено несколько тысяч вполне современных серверов.
При таких масштабах всякие проблемы, которые обычно незаметны, всплывают сразу.
Например, когда мы катим новый clang, то сразу натыкаемся на все багло, которое в него посадили, это сразу видно в CI. Кстати, именно поэтому мы всегда берем версию, которая последняя в своей стабильной ветке, нулевые и первые не берем.
К чему это я?
Когда-то, когда я менял предыдущий дефолт на #tcmalloc, я, для эксперимента, послал в наш CI 3 PR, в каждом из которых менял аллокатор по умолчанию на #tcmalloc, mimalloc, и что-то еще.
В случае tcmalloc PR был "почти зеленый", в остальных PR было прилично посыпавшихся тестов!
Вот, такая вот байка про качество кода tcmalloc.
👍26🔥6🤡3🤮1🥱1
Технологический Болт Генона
Открытка @itpgchannel и его приключениям с malloc 🌝
Грепать в канале по тегу #tcmalloc
👍5❤3🤡3🆒1