Комментарии 17
Окончание статьи огонь и жизненное
Чет намногокодил, можно проще. Обосную:
По аналогии с i18n_patterns
ставим враппер urlpatterns_transformer
на корневой urlpatterns
и на старте сервера превращаем стандартный лист в пропатченный, не надо каждый path ручками менять:
# settings.urls.py
urlpatterns = urlpatterns_transformer([
path("users/<int:user_id>", user_handler),
path("users/me", me_handler),
]
Уже на этапе патчинга (старта сервера) можно проверять наличие статической составляющей, и ставить в Pattern
:
path( .... Pattern=PrefixRoutePattern if idx and idx !=1 else RoutePattern)
Но и это так себе улучшение, тогда уж третий StaticRoutePattern
нужен. Но и это не надо делать, поскольку для префиксов, есть отличное решение с include
, померяйте относительно примеров в статье с вот таким вариантом:
#urls = [
# my_path("users/<int:user_id>", user_handler),
# my_path("users/me", me_handler),
#]
urlpatterns = [path("users/", include('users.urls')),]
# users.urls.py
urlpatterns = [
path("<int:user_id>", user_handler),
path("me", me_handler),
]
Если не нравится новый файл - include принимает и контейнер с url:
class users_urls:
urlpatterns = [path("int:user_id", user_handler), path("me", me_handler)]
urlpatterns = [path("users/", include(users_urls, 'users_sub_url')),]
Мне кажется, что результат удивит.
Как вариант копания URLdispatch предлагаю посмотреть на сепарирование urls по методам [GET, POST, PATCH], так делают многие фреймворки. Вот тут будет интересный расклад, если PATCH редкий, то он будет срабатывать максимально быстро. Я рассказывал об этом на своем недавнем докладе про "Django FTL", там же линк на репо.
Ну и конечно не плакать надо над 10 секундами ожидания ответа базы, а смотреть, что за ерунда творится. В качестве примера если есть условие с OR c несколькими JOIN - вероятно стоит переехать на Subquery, оказывается, он может работать быстрее, но без explain все равно говорить не о чем - нет информации.
Желаю автору @deliro успехов c Django, там много чего стоит подкручивать. И в первую очередь точно не url.
,,,
8. Переходить на Go ))
Эта оптимизация пришла в джанго из сервиса, который мы переписывали с питона на раст, где роутер удалось ускорить в 700 раз (по сравнению с aiohttp'шным — с 300мкс до 450нс в худших случаях). Так что, полностью поддерживаю восьмой пункт:) Но есть большая куча проектов, которые нельзя просто взять и переписать по желанию.
Я немножко из другой области. Но, если у вас пути это константы, можно не только разбить на группы, а и вытянуть все параметры, все префиксы. Для каждого куска посчитать хеши ну и длина будет известна.
И получается, только входную строку нужно будет разбить. А потом аля дерево по хешам кусков. Как то так. Это просто мысли, не ругайте.
Я уже подумал что-то с роутерами(домашними) на джанге запили, а тут роуТЫ, автор забайтил - реп
Если микросекунды имеют хоть какое-то значение, то, возможно, следует использовать C++/Rust, а не Python+Django.
Наверно, по префиксам удобно сделать префиксное дерево, чтобы не проходиться по всем префиксам в цикле
Я бы еще поработал с каждым роутом с переменными: для числа элементов от 100 до (условно) 1млн можно генерировать все варианты при старте приложения до первых клиентов и хранить их в удобной для поиска структуре (например, некий аналог хешмапы с доступом О(1) при отсутствии коллизий).
Ну ладно вы router (читается [рутер] или [раутер]} произносите как [роутер], но маршрут-то всегда был рутом! Такая боль!
Ускорение роутера в Django в 51 раз