# Анализ бенчмарка bench_full.sh — 2026-05-20 ## Контекст Запущен полный бенчмарк `bench-func/bench_full.sh` (RUNID=9248232). Namespace: `fission-08f114ea3595cccf` (sub: bench@bench.local). 4 языка × 4 размера (tiny/small/medium/large) + 4 архивных теста = 20 итого. --- ## Результаты bench_full.sh | LANG | SIZE | UPLOAD(ms) | COLD(ms) | HOT_AVG(ms) | STATUS | |--------|---------|-----------|---------|------------|----------------| | python | tiny | 2529 | 3317 | 1198 | OK | | python | small | 2764 | 1387 | 1182 | OK | | python | medium | 2762 | 1374 | 1185 | OK | | python | large | 2769 | 1366 | 1653 | OK | | nodejs | tiny | 3158 | 9410 | 1172 | OK (аномалия*) | | nodejs | small | 2751 | 1559 | 1193 | OK | | nodejs | medium | 2754 | 2471 | 1158 | OK | | nodejs | large | 2745 | 1583 | 1190 | OK | | ruby | tiny | 3142 | 3255 | 1162 | OK | | ruby | small | 2737 | 1402 | 1181 | OK | | ruby | medium | 3151 | **80451** | 115 | OK (аномалия!) | | ruby | large | 1116 | 2448 | 104 | OK | | php | tiny | 1137 | 2528 | 1200 | OK | | php | small | 2747 | 1469 | 1158 | OK | | php | medium | 2749 | — | — | **COLD-TIMEOUT** | | php | large | 2725 | — | — | **COLD-TIMEOUT** | | python | archive | 2749 | 1403 | 1176 | OK | | nodejs | archive | 2777 | 1539 | 535 | OK | | ruby | archive | 1367 | 821 | 787 | OK | | php | archive | 2744 | 1575 | 1189 | OK | **ИТОГ: PASS=18, FAIL=2** *nodejs/tiny cold=9410ms — одиночный выброс, не воспроизводился. --- ## Аномалия: ruby/medium cold=80451ms ### Анализ Проведено ×6 независимых прогонов (diag_bugs.sh, два запуска): - 3780 / 1402 / 1384 / 3225 / 1435 / 1773 ms **Вывод:** не воспроизводится. Разовый выброс (вероятно node pressure или transient network). **Статус: ЗАКРЫТ. Не баг.** --- ## Баг: PHP medium + large COLD-TIMEOUT ### Первичная гипотеза (верна) `bench_full.sh` генерирует PHP код для medium/large с arrow functions (PHP 7.4+): ```php // medium array_map(fn($s) => strrev(strtoupper($s)), $words) array_map(fn($x) => ($x - $m) ** 2, $data) // large array_map(fn($i) => array_map(fn($j) => ..., ...), ...) ``` PHP env на кластере — версия **< 7.4**. Arrow syntax → Parse error → pod возвращает 500. PHP tiny/small и PHP archive — используют традиционный синтаксис без `fn()=>` → OK. ### Механизм pool exhaustion (важно!) При invoke сломанной функции: 1. Executor берёт pool pod → специализирует под функцию 2. PHP парсер: Parse error → возвращает 500 3. Executor считает это ошибкой вызова → ретраит следующий pod 4. 20 ретраев × 5s = 100s → COLD TIMEOUT 5. За это время пул (`console-php-env`) в namespace исчерпан **Следствие:** php/large идёт ПОСЛЕ php/medium. К моменту его запуска пул уже разрушен → php/large тоже COLD TIMEOUT даже если бы его код был правильным. ### Диагностика diag_bugs.sh — что мы делали Создан скрипт `bench-func/diag_bugs.sh` с 6 тестами: 1. `php-arrow-min` — минимальный PHP с `fn($x)=>$x*2` 2. `php-version` — только `return PHP_VERSION` (стандартный PHP) 3. `php-med-noarr` — medium логика через foreach вместо arrow 4. `ruby-med-1/2/3` — ruby/medium ×3 независимых функции ### Ошибки в процессе диагностики **Ошибка 1: SIGPIPE при `| tee`** Первый прогон завершился досрочно — скрипт через SSH pipe убивался SIGPIPE при прокрутке/чтении терминала. Исправлено: nohup + прямая запись в файл. **Ошибка 2: 5 параллельных прогонов diag_bugs.sh** В процессе диагностики случайно накопилось 5+ одновременных процессов `diag_bugs.sh` на VM (PIDs: 2476997, 2478955, 2480445, 2482045, 2482452). Все конкурировали за PHP pool → дополнительный pool exhaustion. **Следствие:** тесты `php-version` и `php-med-noarr` тоже дали COLD TIMEOUT — не из-за собственного бага, а из-за занятого пула. ### Что реально подтверждено vs что предполагается | Факт | Статус | |------|--------| | `fn()=>` вызывает COLD TIMEOUT | **ПОДТВЕРЖДЕНО** (×2 прогона) | | PHP env версия < 7.4 | **ПРЕДПОЛОЖЕНИЕ** (php-version не дал ответа из-за pool exhaustion) | | php-version FAIL = самостоятельный баг | **ОПРОВЕРГНУТО** — следствие pool exhaustion | | php-med-noarr FAIL = PHP env broken | **НЕ ПОДТВЕРЖДЕНО** — тест не прошёл чисто | ### Что НЕ удалось выяснить - Точная версия PHP в env образе - Работает ли `php-med-noarr` (medium без arrow) в изолированном тесте --- ## Механизм pool exhaustion — общая проблема Одна функция с синтаксической ошибкой может "заморозить" весь PHP пул namespace: 1. Сломанная функция → 20 ретраев × пул pod 2. Пул исчерпан → **все остальные PHP функции того же пользователя** получают COLD TIMEOUT 3. Пользователь видит что "рабочая" функция сломалась — не понимает почему В реальном проде это критично: один неосторожный деплой = все PHP функции пользователя не отвечают. ### Почему pod "держится" Pool pod ≠ выполнение кода. Pod — контейнер-заготовка. При invoke: - Executor специализирует pod (загружает код через /specialize) - PHP парсер падает → 500 → executor ретраит СЛЕДУЮЩИЙ pod - Каждый ретрай = новый pod из пула Pod не "держится" в одном — executor расходует пул по одному pod'у за ретрай. ### Системные решения (не реализованы) 1. **Circuit breaker в executor** — после N провалов подряд для одной функции → вернуть ошибку, не трогать пул 2. **Синтаксическая валидация при upload** — `php -l`, `python3 -m py_compile`, `ruby -c`, `node --check` — сломанный код не попадает в систему 3. **Pool size limit per namespace** — ограничить max pods на env × namespace Вариант 2 (валидация при upload) — реализуем в нашем коде (fission-console), остальные — в fission-bundle. --- ## Предложения — что делать ### Приоритет 1 (быстро): исправить bench_full.sh Заменить arrow functions в PHP medium/large на традиционный синтаксис. - `fn($s) => strrev(strtoupper($s))` → `function($s){ return strrev(strtoupper($s)); }` - `fn($x) => ($x - $m) ** 2` → foreach цикл - Аналогично для large (вложенные array_map) После фикса запустить bench_full.sh заново — должно быть PASS=20. ### Приоритет 2 (чистая диагностика): проверить php-med-noarr Убить фоновые процессы на VM, запустить одиночный тест php-version/php-med-noarr в изоляции — убедиться что PHP env работает для стандартного кода. ### Приоритет 3 (системный): валидация кода при upload Добавить в fission-console синтаксическую проверку кода перед созданием функции. Защита от pool exhaustion для всех пользователей. --- ## Файлы - `bench-func/bench_full.sh` — основной бенчмарк (требует фикс PHP medium/large) - `bench-func/diag_bugs.sh` — диагностический скрипт (создан в этой сессии) - `test-results/bench-func/` — логи прогонов