TGViewer
Zen of Python Zen of Python @zen_of_python · 18.9K subscribers
Post #4876 2.6K
Разбор HTML-страницы за 272 микросекунды вместо 15,3 миллисекунды

Бернат Габор собрал turbohtml, набор инструментов для HTML целиком на C: экранирование, разэкранирование, токенизация, запросы по селекторам, сериализация и операции с URL. Разбор страницы на 92 КБ занимает 272 мкс против 15,3 мс у BeautifulSoup, запрос по селектору 1,3 мкс против 20,8 мкс у lxml и 99,9 мкс у BeautifulSoup, токенизация 34,9 мкс против 435 мкс у html.parser и 836 мкс у html5lib. На плотном четырёхмегабайтном тексте escape отрабатывает за 4,98 мс против 12,7 мс у html.escape. Публикация от 18 июня обновлена 10 июля.

Скорость складывается из того, как обрабатываются байты. Обычный код ищет спецсимволы посимвольно, и процессор на каждом байте выполняет ветвление. Здесь байты обрабатываются пачками: SWAR складывает восемь байт в одно машинное слово и проверяет их арифметикой, SIMD делает то же самое сразу по шестнадцать байт одной инструкцией. Ветвлений в горячем цикле почти не остаётся.

🔘 длина результата сначала считается точно, потом выделяется одним куском и заполняется массовым копированием, вместо дописывания по мере разбора;
🔘 токенизатор сохраняет исходную ширину строки и компилируется в три варианта под UCS-1, UCS-2 и UCS-4;
🔘 чистые текстовые куски возвращаются как срезы без копирования, копия делается только когда она правда нужна;
🔘 переписывание css_path() с квадратичного перебора на индекс сократило пример со 112 мс до 0,9 мс;
🔘 список переиспользуемых обёрток ускорил find_all() с 1,9 до 1,4 мкс, но в сборке без GIL он отключён.

Автор оговаривает, что Callgrind считает инструкции, а не реальное время по часам, поэтому на него опираются только при сравнении вариантов. Корректность проверяется побайтовым сравнением с эталонными библиотеками, сборками с ASan и UBSan и фаззингом.

Что у вас парсит HTML в проде и сколько времени на это уходит?

@zen_of_python
  • 🔥 8
  • 🤣 1
  • 👀 1
More from @zen_of_python
  1. Sep 20, 2026Как collections.deque хранит элементы блоками У deque два конца, поэтому легко представить…
  2. Sep 20, 2026Что ускоряет django-msgspec в Django и где он расходится с json django-msgspec заменяет ко…
  3. Sep 20, 2026Почему миллион чисел в Python занимает 35 МБ Список из миллиона целых, которые помещаются…
  4. Sep 19, 2026Как перевести Python-сервер MCP с FastMCP на SDK 2.x Свежая установка зависимостей сломала…
  5. Sep 19, 2026Как кэшировать методы чужого Python-клиента Если библиотечный клиент нельзя менять, его ме…
  6. Sep 19, 2026Где заканчивается ускорение NumPy и что выбрать дальше Векторизация выполняет цикл низкоур…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →