
# Paralelní pracovní procesy

Greph rozděluje textové skenování a skenování AST mezi pracovní procesy, pokud je práce dost rozsáhlá, aby vyvážila režii. Fond je založen na `pcntl_fork()` a při nedostupnosti `ext-pcntl` (Windows, některá prostředí PaaS, omezený hosting) přechází na zpracování v rámci procesu.

## Zapnutí paralelního skenování

Nastavte `-j N` v CLI nebo `jobs: N` v příslušném objektu 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),
);
```

## Kdy se aktivuje paralelní zpracování

Greph neparalelizuje bezpodmínečně. Spouštění N procesů a předávání jejich výsledků přes roury přináší režii, která u malých seznamů souborů převýší náklady samotného vyhledávání. Fasáda proto vypočítá práh podle počtu úloh, režimu vyhledávání a tvaru vzoru. Do fondu pracovních procesů se předávají pouze seznamy souborů překračující tento práh.

Aktuální heuristiky (v `Greph\Greph::shouldUseTextWorkers` a souvisejících částech):

- Běhy s jedinou úlohou (`-j 1`) se vždy zpracovávají v rámci procesu.
- Výchozí textové skenování vyžaduje přibližně `jobs * 2_000` souborů, než se fond aktivuje.
- Režimy počítání, souborů se shodami a souborů bez shod snižují práh přibližně na `jobs * 750`, protože zpracování jednotlivých souborů je levnější.
- U krátkých vzorů pevného řetězce připomínajících identifikátory se práh zvyšuje přibližně na `jobs * 4_000`, protože rychlá cesta pro doslovné řetězce je už tak velmi levná a spouštění dalších procesů se málokdy vyplatí.
- Vyhledávání a přepis AST používají práh `jobs * 750`.

Jde o heuristické hodnoty, nikoli záruky. Jsou vyladěné podle výkonnostního korpusu WordPress a mohou se změnit.

## Jak fond funguje

`Greph\Parallel\WorkSplitter` rozdělí seznam souborů do N částí. `Greph\Parallel\WorkerPool` spustí pro každou část jeden pracovní proces; každý pracovní proces provede stejnou funkci nad svou částí a `Greph\Parallel\ResultCollector` přečte serializované výsledky přes dvojici socketů Unix pro každý proces. Nadřazený proces vyčká na všechny pracovní procesy a poté sloučí a znovu seřadí výsledky, aby jejich pořadí zůstalo stabilní bez ohledu na rozdělení práce.

V textovém režimu fond pracovních procesů používá vlastní přenosový kodek (`Greph\Text\TextResultCodec`), aby udržel serializovaný obsah malý. Režim AST používá standardní `serialize()` knihovny PHP.

## Když pcntl není k dispozici

Pokud `pcntl_fork` nelze volat (Windows, sestavení PHP se zvýšeným zabezpečením), fond transparentně přejde ke zpracování každé části v rámci procesu. Výsledek je stejný jako u `-j 1`. Greph nevyvolá chybu; pouze běží v jednom vlákně.

To lze za běhu zjistit kontrolou `function_exists('pcntl_fork')`.

## Doporučení pro ladění

- Začněte s nastavením `-j` na polovinu počtu fyzických jader a zvyšujte ho, dokud nepřestanete pozorovat zlepšení.
- U vyhledávání pouze doslovných pevných řetězců v malých repozitářích je zpracování v jediném procesu obvykle rychlejší než jakákoli paralelní konfigurace.
- Žádný publikovaný výkonnostní test neměří paralelní vyhledávání ani přepis AST. Než zvolíte počet úloh, proveďte měření na vlastním stromu.
- Řádky „Režim skenování: paralelní text“ v README (`1`, `2` a `4` pracovních procesů nad korpusem WordPress) fond neměří: vyhledávají krátký doslovný řetězec `function`, jehož práh `jobs * 4_000` souborů převyšuje velikost korpusu, takže každý řádek běží v rámci jediného procesu ([#8](https://github.com/inline0/greph/issues/8)).

## Omezení

- Aktuální fond nepodporuje kradení práce. Pokud je jedna část výrazně náročnější než ostatní, fond čeká na nejpomalejší pracovní proces.
- Výsledky pracovních procesů se ukládají do vyrovnávací paměti, dokud všechny neskončí. Paralelní režim nepodporuje průběžný výstup dlouhotrvajícího skenování (způsob, jakým `rg --json` streamuje události).
- Nadřazený proces po sloučení výsledky znovu seřadí, takže fond pracovních procesů nesnižuje špičkovou spotřebu paměti oproti skenování v jediném procesu.

Tato omezení jsou přijatelná pro úlohy, na které se Greph zaměřuje (interaktivní vyhledávání v kódu, smyčky agentů, úlohy CI nad snímky). Pokud profilování odhalí úzké místo při práci s reálnými korpusy, omezení znovu posoudíme.
