
От struct к компиляции под схему: ускоряем RowBinary-декодер на Python
Я автор aiochlite — асинхронного клиента ClickHouse на aiohttp. Раньше мой декодер RowBinary читал каждое числовое поле отдельно. Если брать 200 тысяч строк с десятью числовыми колонками, получалось два миллиона таких чтений, хотя все данные уже были в памяти.Сначала я думал использовать Cython, C или Rust. Но потом решил попробовать оптимизировать сам процесс: объединить соседние поля с фиксированной длиной в один struct, а полностью фиксированные строки разбирать с помощью Struct.iter_unpack. На числовых данных это ускорило работу примерно в 8.3 раза.Со смешанной схемой данных получилось интереснее: простая склейка почти не помогла. Главной проблемой осталась проверка типов внутри основного цикла. В итоге я начал генерировать и компилировать Python-функцию под конкретную схему ответа — это дало ускорение еще примерно в 1.7 раза.В статье я подробно рассказываю, как это работает, как я проводил замеры, сколько времени занимает генерация кода и в каких случаях такие оптимизации уже не нужны. Весь код и скрипты для тестов можно найти в репозитории. Читать далее