Comments 17
На php надо было писать :)
Не понял где именно была просадка производительности в старом решении.
Было бы интересно посмотреть на эффект values до использования Rust. Я как-то сделал мега оптимизацию вызова ендпоинта по памяти просто не загружая в память то, что не использовалось.
Привет, по сути основная просадка заключается в том, как собирается древовидная структура (маппинг по id сначала дерева съютов и затем маппинг кейсов к этим съютам), нам нужно отдать все данные разом, и более того этот endpoint отвечает за поиск и должен быть сильно отзывчивым, чтобы фронт мог подгрузить дерево выбора, и условие в том что фронт мы менять не можем, DRF сериализатор при сборе всех данных которые нам нужны использует related managers, и это получается сильно дорого, так как это все получение ORM объектов и их cpu-bound сериализация, если мы исключим Rust из уравнения и сделаем в python тоже самое, что мы отдали на выполнение Rust-у c использованием values, то получим результат быстрее, чем DRF, но он все равно будет хуже чем у раста потому что все равно остается cpu-bound задача на циклах, в самом большом проекте, который у нас есть, решение на values и простых циклах в python мы получаем +-8 секунд, с Rust результат меньше секунды.
а я всё равно не понял, где там циклы. максимум -- поиск по индексу там должен быть, с ним 100к небольших объектов сериализовать должно быть реально за секунду.
Интуитивно кажется что так и есть.
@RomanKabaev а есть вомзожность пошарить, что подаётся на вход и что получается на выходе у rust библиотеки?
Я бы попробовал выжать из Питона пару секунд времени.
Привет, возможность скинуть данные нет, но есть подозрение что я допустил ошибку когда сравнивал перформанс, в детали пока вдаваться не буду, сейчас большая загрузка на проектах, постараюсь вернуться с развернутым ответом в ближайшую неделю/на следующей неделе, как только протестирую все еще раз.
А если сравнить с версией 3.12, какой прирост по производительности будет?
Ещё б ржавый код каким-нибудь clippy обработать, а то местами оно выглядит несколько странно и неконсистентно, в сравнении с тем же питоном - приколы типа x.borrow().clone()
пополам с Rc::clone()
.
Я не Rust разработчик и про лучшие практики знаю мало, но судя по этому правилу такое написание рекомендуется для Ref counter-ов https://rust-lang.github.io/rust-clippy/master/index.html#/clone_on_ref_ptr
Я понял, что ошибся. Думал что вы в первом случае тоже ссылку копируете, но копируются данные. С другой стороны не очень понятно зачем их клонировать, когда сами данные кажется достаточно локальные и можно целиком отдать их в чужое владение, просто развернув их из умного указателя. Но тут вам определённо виднее.
Очень странные дела. А точно нельзя было языком SQL решить кейс? Ну из плоского сделать дерево - вроде умеет.
Впервые вижу чтобы были проблемы json отдать в питоне. Хотя мы FastAPI используем и тоже orjson, ijson или как его там. Всё быстро дампиться в json строку.
Но статья прикольная. Плагин на Rust - это мощно
Присоединяйтесь к бесплатному курсу по Rust на платформе Stepik :)
У меня была подобная задача ровно 10 лет назад. Выкрутился тем, что написал хранимку на pl/v8 (pl/upython на AWS нельзя использовать, т.к. он untrusted). Причём сборка json была выполнена с помощью склейки частей. Результат был порядка 50Mb.
Но у этой байки счастливый финал. За три месяца мы отрефакторили архитектуру и выбросили этот костыль.
Самый быстрый фреймворк на Диком Западе: ускоряем Django-rest-framework вместе с Rust