
# Vzporedni delavci

Greph razporedi pregledovanje besedila in AST med skupino delavcev, ko je obseg dela dovolj velik, da upraviči režijske stroške. Skupina temelji na `pcntl_fork()` in preide na izvajanje znotraj procesa, kadar `ext-pcntl` ni na voljo (Windows, nekatera okolja PaaS in omejeno gostovanje).

## Omogočanje vzporednega pregledovanja

Nastavite `-j N` v CLI ali `jobs: N` v ustreznem objektu z možnostmi:

```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),
);
```

## Kdaj se začne vzporedno izvajanje

Greph ne izvaja vzporedno v vseh primerih. Razvejitev v N procesov in izmenjava rezultatov prek cevi ustvarjata režijske stroške, ki pri majhnih seznamih datotek prevladajo nad samim iskanjem. Zato fasada izračuna prag glede na število opravil, način iskanja in obliko vzorca. V skupino delavcev se pošljejo samo seznami datotek, ki presegajo prag.

Trenutne hevristike (v `Greph\Greph::shouldUseTextWorkers` in sorodnih datotekah):

- Zagoni z enim opravilom (`-j 1`) se vedno izvajajo znotraj procesa.
- Pri običajnem pregledovanju besedila mora biti približno `jobs * 2_000` datotek, da se vključi skupina.
- Načini štetja, datotek z zadetki in datotek brez zadetkov znižajo prag na približno `jobs * 750`, ker je delo na posamezni datoteki cenejše.
- Pri kratkih vzorcih fiksnih nizov, oblikovanih kot identifikatorji, se prag zviša na približno `jobs * 4_000`, ker je hitra pot za dobesedne nize že tako poceni, da se razvejanje redko izplača.
- Iskanje in prepis AST uporabljata prag `jobs * 750`.

Te številke so hevristike, ne zagotovila. Prilagojene so korpusu primerjalnih preizkusov WordPress in se lahko spremenijo.

## Kako deluje skupina

`Greph\Parallel\WorkSplitter` razdeli seznam datotek na N kosov. `Greph\Parallel\WorkerPool` razveji en delovni proces za vsak kos, vsak delavec zažene isto zaključeno funkcijo na svojem delu, `Greph\Parallel\ResultCollector` pa prebere serializirane rezultate prek para vtičnic Unix za vsakega delavca. Nadrejeni proces počaka na vse delavce, nato združi in znova razvrsti rezultate, da ostane vrstni red izhoda stabilen ne glede na razdelitev dela.

Za besedilni način skupina delavcev uporablja prilagojen kodek za prenos (`Greph\Text\TextResultCodec`), da ohrani serializirano vsebino kompaktno. Način AST uporablja standardni `serialize()`, ki ga ponuja PHP.

## Ko pcntl ni na voljo

Če `pcntl_fork` ni mogoče klicati (Windows, utrjene gradnje PHP), skupina brez opozorila preide na izvajanje vseh kosov znotraj procesa. Rezultat je enak kot pri `-j 1`. Greph ne sproži napake; deluje le z eno nitjo.

To lahko med izvajanjem preverite z `function_exists('pcntl_fork')`.

## Nasveti za prilagajanje

- Začnite tako, da nastavite `-j` na polovico števila fizičnih jeder, nato pa vrednost povečujte, dokler izboljšave ne prenehajo.
- Pri iskanju samo dobesednih fiksnih nizov v majhnih repozitorijih je izvajanje v enem procesu običajno hitrejše od katere koli vzporedne konfiguracije.
- Objavljeni primerjalni preizkusi ne merijo vzporednega iskanja ali prepisa AST. Preden določite število opravil, opravite meritve na svojem drevesu.
- Vrstice README »Način pregledovanja: vzporedno besedilo« (`1`, `2` in `4` delavci na korpusu WordPress) ne merijo skupine: iščejo kratek dobesedni niz `function`, katerega prag `jobs * 4_000` datotek presega velikost korpusa, zato se vse vrstice izvajajo znotraj enega procesa ([#8](https://github.com/inline0/greph/issues/8)).

## Omejitve

- Trenutna skupina ne podpira kraje opravil. Če je en kos veliko zahtevnejši od drugih, skupina čaka na najpočasnejšega delavca.
- Rezultati delavcev se medpomnijo, dokler vsi ne končajo. Pretakanje izhoda dolgotrajnega pregledovanja (kot `rg --json` pretaka dogodke) v vzporednem načinu ni podprto.
- Nadrejeni proces po združitvi znova razvrsti rezultate, zato skupina delavcev ne zmanjša največje porabe pomnilnika v primerjavi s pregledovanjem v enem procesu.

Te omejitve so sprejemljive za delovne obremenitve, na katere cilja Greph (interaktivno iskanje kode, zanke agentov, opravila CI nad posnetki). Ponovno jih bomo preučili, če profiliranje pokaže, da predstavljajo ozko grlo pri resničnih korpusih.
