
# Paralelné procesy

Greph rozdeľuje textové skenovanie a skenovanie AST medzi skupinu procesov, keď je objem práce dostatočne veľký, aby vyvážil réžiu. Skupina je založená na `pcntl_fork()` a ak `ext-pcntl` nie je dostupné, použije vykonávanie v rámci procesu (Windows, niektoré prostredia PaaS, obmedzené hostingové prostredia).

## Povolenie paralelného skenovania

Nastavte `-j N` na CLI alebo `jobs: N` v príslušnom objekte možností:

```bash
./vendor/bin/greph -F -j 8 "function" src
./vendor/bin/greph -p '$obj->$method($$$ARGS)' -j 4 src
./vendor/bin/rg --threads 8 -F "function" src
./vendor/bin/sg run --threads 8 --pattern '$obj->$method($$$ARGS)' src
```

```php
use Greph\Greph;
use Greph\Text\TextSearchOptions;

Greph::searchText(
    'function',
    'src',
    new TextSearchOptions(fixedString: true, jobs: 8),
);
```

## Kedy sa spustí paralelné spracovanie

Greph nespúšťa paralelné spracovanie bezpodmienečne. Vytváranie N procesov a prenos ich výsledkov cez rúry prináša réžiu, ktorá pri malom počte súborov prevýši samotné vyhľadávanie. Rozhranie preto vypočíta prahovú hodnotu podľa počtu úloh, režimu vyhľadávania a tvaru vzoru. Do skupiny procesov sa odovzdajú iba zoznamy súborov nad touto hranicou.

Aktuálne heuristiky (v `Greph\Greph::shouldUseTextWorkers` a súvisiacom kóde):

- Spustenia s jednou úlohou (`-j 1`) sa vždy vykonávajú v rámci procesu.
- Predvolené textové skenovanie vyžaduje približne `jobs * 2_000` súborov, aby sa aktivovala skupina procesov.
- Režimy počet, súbory so zhodami a súbory bez zhôd znižujú prah na približne `jobs * 750`, pretože práca na jeden súbor je menšia.
- Krátke vzory pevných reťazcov v tvare identifikátora zvyšujú prah na približne `jobs * 4_000`, pretože rýchla cesta pre doslovné reťazce je už taká lacná, že vytváranie procesov sa zvyčajne nevyplatí.
- Vyhľadávanie a prepisovanie AST používajú prah `jobs * 750`.

Tieto čísla sú heuristiky, nie záruky. Sú vyladené podľa testovacieho korpusu WordPress a môžu sa zmeniť.

## Ako funguje skupina procesov

`Greph\Parallel\WorkSplitter` rozdelí zoznam súborov na N častí. `Greph\Parallel\WorkerPool` vytvorí pre každú časť samostatný proces, ktorý spustí rovnakú uzávierku nad svojím úsekom, a `Greph\Parallel\ResultCollector` načíta serializované výsledky cez samostatnú dvojicu Unix socketov pre každý proces. Nadriadený proces počká na všetky procesy a potom zlúči a znova zoradí výsledky, aby poradie výstupu zostalo stabilné bez ohľadu na rozdelenie práce.

V textovom režime skupina procesov používa vlastný kodek prenosu (`Greph\Text\TextResultCodec`), aby zmenšila veľkosť serializovaných údajov. Režim AST používa štandardný `serialize()` od PHP.

## Keď pcntl nie je dostupné

Ak `pcntl_fork` nemožno zavolať (Windows, zostavenia PHP so zvýšeným zabezpečením), skupina bez upozornenia prejde na vykonávanie každej časti v rámci procesu. Výsledok je rovnaký ako pri `-j 1`. Greph nevyvolá chybu; jednoducho sa spustí v jednom vlákne.

Túto dostupnosť môžete zistiť za behu kontrolou `function_exists('pcntl_fork')`.

## Odporúčania na ladenie

- Začnite s hodnotou `-j` nastavenou na polovicu počtu fyzických jadier a zvyšujte ju, kým sa výkon neprestane zlepšovať.
- Pri vyhľadávaní iba doslovných pevných reťazcov v malých repozitároch býva jeden proces rýchlejší než akákoľvek paralelná konfigurácia.
- Žiadny publikovaný výkonnostný test nemeria paralelné vyhľadávanie ani prepisovanie AST. Pred výberom počtu úloh si zmerajte výkon na vlastnom strome.
- Riadky „Režim skenovania: paralelný text“ v README (`1`, `2` a `4` procesov na korpuse WordPress) nemerajú skupinu procesov: vyhľadávajú krátky doslovný reťazec `function`, ktorého prah `jobs * 4_000` súborov je vyšší než veľkosť korpusu, takže všetky riadky sa vykonávajú v rámci jedného procesu ([#8](https://github.com/inline0/greph/issues/8)).

## Obmedzenia

- Aktuálny fond nepodporuje preberanie práce. Ak je jeden blok výrazne náročnejší než ostatné, fond čaká na najpomalšieho pracovníka.
- Výsledky pracovníkov sa ukladajú do vyrovnávacej pamäte, kým všetci nedokončia. Streamovanie výstupu z dlho bežiaceho skenovania (ako `rg --json` streamuje udalosti) nie je v paralelnom režime podporované.
- Rodičovský proces po zlúčení výsledky znova zoradí, takže fond pracovníkov neznižuje špičkové využitie pamäte v porovnaní so skenovaním v jednom procese.

Tieto obmedzenia sú prijateľné pre pracovné zaťaženia, na ktoré sa Greph zameriava (interaktívne vyhľadávanie v kóde, cykly agentov, úlohy CI nad snímkami). Znovu sa posúdia, ak profilovanie ukáže, že predstavujú úzke miesto pri práci so skutočnými korpusmi.
