Files
drhider/History/code-fixes/2026-08-19-replacer-optimization.md
T

46 lines
2.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# v0.0.39 — оптимизация apply_replacements (однопроходная замена) — 2026-08-19
**Дата:** 2026-08-19
**Версия:** 0.0.38 → 0.0.39
**Файл:** `drhider/replacer.py`, `site/app.py` (версия)
---
## Суть
Обфускация PDF 19 МБ шла 132.7с, из них ИИ (LLM) всего 7с — остальное (~125с)
тратил основной код. Замер выявил узкое место: `apply_replacements`.
## Причина
`apply_replacements` для **каждой** сущности из mapping делала **2 полных
прохода `re.sub` по всему тексту** (основной + фоллбэк `_md_tolerant_pattern`).
Сложность O(N_сущностей × размер_текста × 2) — квадратичная по числу сущностей.
При 300+ сущностей и тексте в несколько МБ — десятки секунд.
Замер (0.9 МБ, 304 сущности): **17.3 с**.
## Решение
Однопроходная замена:
- Все ключи собираются в **один** regex-паттерн через альтернацию `(?:...|...)`
(по убыванию длины, с `re.escape`, границы `(?<!\w)...(?!\w)` для alnum-сущностей).
- Один `re.sub` с callback (lookup в mapping), O(text).
- Фоллбэк `_md_tolerant_pattern` применяется **только к ключам, не найденным**
основной заменой (отслеживание через `matched_keys`), а не ко всем.
## Результат замера
- 300 сущностей реально в тексте (1.3 МБ): **1.17 с** (было бы десятки сек).
- Реалистичный сценарий (10 сущностей): **0.29 с**.
- Согласованность токенов и mapping.csv сохранены (проверено через `obfuscate`).
## Проверка
- `test_replacer` 10/10, `test_builder` 20/20, `test_scanner` 20/20, `test_zip` 28/28.
- Пайплайн `obfuscate`: «ООО Ромашка»→«Вектор_0001» в двух файлах согласовано,
mapping.csv корректен.
## Примечание
- `scan_regex` (0.4с) и upload (сеть ~1.7 МБ/с) — не узкие места, не трогали.
- `pdf_to_markdown` (pdfplumber) локально не замерен (нет библиотеки); остаётся
потенциальным вторым узким местом для будущей оптимизации (pypdf/pdfminer).