Инженерной боли пост. С надеждой на дельные советы
Все началось с pet-проекта, который использовал polars(сорцы) и должен был крутиться в Docker на моем домашнем NAS, в следующей конфигурации:
CPU arm/v7 32-bit, Annapurna Labs Alpine AL314 Quad-core ARM Cortex-A15
4Гб RAM
ОС QNAP QTS на linux ядре 4.2.8 с увеличенным до 32k размером страницы памяти, и с официальной поддержкой Docker
Спойлер: принципиальное решение проблемы - найдено. Купил маленькую коробочку на "мейнстримной" архитектуре, на которой все цветет и пахнет.. кроме моего внутреннего(ну и внешнего, че уж там) инженера) Так что решение выкинуть железку - можно не предлагать
Так вот, пока я писал код, и готовил сборочные скрипты ничто не предвещало беды - я спокойно потестил код локально, написал Dockerfile для сборки на poetry. Настало время развернуть это все на NAS - казалось бы ARM уже давно мейнстрим, но тут понеслось
python как всегда лишь удобный биндинг к куче платформозависимого кода) подавляющее большинство python-зависимостей под arm/v7 приходится компилировать
готовых бинарников polars под arm/v7 - тоже нет
Никаких блокеров к тому, чтобы собрать polars под arm/v7 я не нашел. Но скомпилить его нативно на 4Гб ОЗУ - не получится, даже с минимальными оптимизациями. Нужна кросс-компиляция. Благо с rust и maturin(которым собирается polars) - это несложно, target
armv7-unknown-linux-gnueabihf
в хорошем tier-е поддержкизабегая чуть вперед указываем окружение для сборки аллокатора jemalloc(по умолчанию в polars) под 32k страницу
Итак, усложняем сборку Docker(см. repro) - используем кросс-компиляцию, энв-переменные, QEMU, охапку дров и теперь у нас есть приложка, которая успешно стартует в докере на целевой железке. Вот только за рамками самых примитивных тестов - OOM-ится, причем память точно есть, никакой OOM-киллер процесс не убивает(на всякий случай смотрим лимиты cgoup) - оно "шамо":
memory allocation of 1345920 bytes failed
(подробные логи можно посмотреть по ссылкам в конце поста)
Что же делать?
пробуем mimalloc - он использует для конфигурации рантайм(getconf), эффект - тот же
пробуем env-крутилки, в частности
arena_reserve
может стоит просто меньше резервировать - но нет, просто больше попыток, но по факту все равно OOMпомимо jemalloc и mimalloc не работают также: стандартный аллокатор rust(чем бы он ни был), libc-аллокатор и версия mimalloc, установленного как системная библиотека
И вот на этом месте я застрял. Я не большой спец по системному программированию - не понимаю куда копать
Общение с поддержкой QNAP свелось к
Справедливости ради они еще дали советов что попробовать, но это я уже попробовал до них Пытался отлаживать приложение в gdb - никаких аномальных трейсбэков во время OOM не увидел: rust честно пытается аллоцировать большой raw_vec(трейс есть в вопросе на stackoverflow)
Как-то глубоко копать переменные не получается, т.к. дебаг-символы для бинарника polars получаются слишком большими
BFD: error: /app/.venv/lib/python3.12/site-packages/polars/polars.abi3.so(.debug_str) is too large (0x498a9fd1 bytes)
Я сделал небольшое repro на голом расте - там эта проблема не воспроизводится, значит базово бинарная совместимость - в порядке
Есть несколько гипотез, но я не знаю как их проверить
возможно, кривая вся адресация, но ее проверить я тоже не могу
возможно, стоит чего-нибудь половить в ядре bpf-ом, но что..
кастомное ядро 4.2.8 кастомный дистриб(QTS) не богат средствами отладки - как я понял там запускается busybox набор утилит
В итоге я завел
вопрос на stackoverflow - там есть логи аллокатора и трейсбэк
repro-проект с минимальным примером на котором проблема воспроизводится
Но активности там не очень много(
А мне бы хотелось все-таки дожать диагностику и однозначно ответить на вопрос: это лыжи не едутя не умею собирать приложения под нужное окружение или все-таки целевая платформа не умеет выполнять корректно собранное? Не потому что эту проблему нельзя решить по-другому, а потому что в том, чем пользуешься - хочется разбираться.
Пишите в комментах ваши соображения. Если что-то удастся прояснить - буду держать читателей поста в курсе