45 lines
3.2 KiB
Markdown
45 lines
3.2 KiB
Markdown
# 2026-08-20 — Честный ответ Sonnet об ускорении + реализация А (v0.0.55)
|
||
|
||
## Честный ответ Sonnet (History/2026-08-20-sonnet-query-honest-speed.md)
|
||
Вопрос: можно ли значительно ускорить обработку, не рискуя устойчивостью/таблицами?
|
||
|
||
Ответ Sonnet (принято, согласуется с замерами):
|
||
- **Безопасно ускорить extract_text() на pdfplumber НЕЛЬЗЯ** — pdfminer pure Python,
|
||
CPU-bound, GIL полностью блокирует threading. (Подтверждено: extract_text 64.4с на Spartan10.)
|
||
- A) Безопасно-просто:
|
||
- A1. Threading для .doc (liberta, IO-bound) — N×~120с → ~120с при нескольких .doc.
|
||
- A2. Кэш compiled regex между файлами (проход 2).
|
||
- B) Заметный выигрыш, но с рисками (ОТЛОЖЕНО):
|
||
- B1. ProcessPool по файлам (spawn) — 3 PDF × 25с → ~30с (только 2+ PDF, CPU=2).
|
||
- B2. ProcessPool по страницам (spawn) — Spartan10 64с → ~35с (сложно: content, порядок).
|
||
- C) Не стоит:
|
||
- fork ProcessPool при session в памяти (COW-раздутие, 4Gi на пределе) — только spawn.
|
||
- Threading по страницам/файлам PDF — GIL, ноль.
|
||
- Итог Sonnet: безопасного значительного ускорения ОДНОГО PDF нет. Для набора 2+ PDF —
|
||
B1. При CPU=2 потолок 2x.
|
||
|
||
## Решение пользователя
|
||
«Делай по А, безопасно» — реализованы ТОЛЬКО A1 и A2. B — НЕ отложено (не делаем).
|
||
|
||
## Реализация (v0.0.55)
|
||
|
||
### A1 — threading для .doc (obfuscator.py, проход 1)
|
||
- .doc файлы (конвертация через HTTP liberta, IO-bound) запускаются в
|
||
ThreadPoolExecutor(max_workers=min(4, N_doc)).
|
||
- Основной цикл сохраняет порядок: для .doc берёт future.result(), остальные —
|
||
последовательно. progress_cb/порядок start/done не меняются.
|
||
- Выигрыш: HTTP-конвертация .doc перекрывается с CPU-обработкой PDF/docx.
|
||
|
||
### A2 — кэш compiled regex (replacer.py + obfuscator.py)
|
||
- replacer.py: вынесен `_build_combined_re(sorted_keys)`, `apply_replacements` получил
|
||
параметр `compiled_re=None` (если None — компилирует сам).
|
||
- obfuscator.py: после формирования `self._sorted_keys` компилируется один раз
|
||
`self._compiled_re`, передаётся во все вызовы apply_replacements (проход 2).
|
||
- __init__/finally: _compiled_re инициализируется/очищается.
|
||
|
||
## Проверка
|
||
- Все 106 тестов OK (test_replacer 10/10 — apply_replacements с compiled_re).
|
||
- Интеграция: flat/ (10 файлов) → 5 обработано (EB.md, EB1.md, Spartan10, TKM, mini_78b),
|
||
битые пропущены, .doc через liberta в потоках. 78.3с (в основном Spartan10 64с extract_text).
|
||
- VERSION 0.0.55.
|