
# Parallelle arbejdere

Greph fordeler tekst- og AST-scanninger på en worker-pulje, når arbejdsmængden er stor nok til at retfærdiggøre overheaden. Puljen er baseret på `pcntl_fork()` og falder tilbage til kørsel i samme proces, når `ext-pcntl` ikke er tilgængelig (Windows, visse PaaS-miljøer, begrænset hosting).

## Aktivér parallel scanning

Angiv `-j N` på CLI eller `jobs: N` i det relevante options-objekt:

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

## Hvornår parallelisering starter

Greph paralleliserer ikke altid. Det kræver ressourcer at forgrene N processer og sende deres resultater frem og tilbage gennem pipes, og ved små fillister overstiger denne omkostning selve søgningen. I stedet beregner facaden en tærskel ud fra antallet af job, søgetilstanden og mønsterets form. Kun fillister over tærsklen fordeles til worker-puljen.

De aktuelle heuristikker (i `Greph\Greph::shouldUseTextWorkers` og beslægtede funktioner):

- Kørsel med ét job (`-j 1`) foregår altid i samme proces.
- Standardscanning af tekst kræver cirka `jobs * 2_000` filer, før puljen aktiveres.
- Tilstandene antal, filer med match og filer uden match sænker tærsklen til cirka `jobs * 750`, fordi arbejdet pr. fil er mindre.
- Korte mønstre af faste strenge, der ligner identifikatorer, hæver tærsklen til cirka `jobs * 4_000`, fordi den hurtige bogstavelige søgevej allerede er så billig, at forgrening sjældent kan betale sig.
- AST-søgning og AST-omskrivning bruger tærsklen `jobs * 750`.

Disse tal er heuristikker, ikke løfter. De er tilpasset benchmark-datasættet WordPress og kan blive justeret.

## Sådan fungerer puljen

`Greph\Parallel\WorkSplitter` fordeler fillisten på N dele. `Greph\Parallel\WorkerPool` forgrener én worker-proces pr. del; hver worker kører den samme closure på sin del, og `Greph\Parallel\ResultCollector` læser de serialiserede resultater via et Unix-socketpar pr. worker. Forældreprocessen venter på alle workers og sammenfletter derefter resultaterne og sorterer dem igen, så rækkefølgen i outputtet er stabil, uanset hvordan arbejdet blev fordelt.

I teksttilstand bruger worker-puljen en tilpasset codec til overførsel (`Greph\Text\TextResultCodec`) for at holde den serialiserede payload kompakt. AST-tilstand bruger PHPs standard-`serialize()`.

## Når pcntl ikke er tilgængelig

Hvis `pcntl_fork` ikke kan kaldes (Windows, hærdede PHP-builds), falder puljen automatisk tilbage til at køre hver del i samme proces. Resultatet er det samme som med `-j 1`. Greph udløser ikke en fejl; det kører blot med én tråd.

Du kan registrere dette ved kørsel ved at kontrollere `function_exists('pcntl_fork')`.

## Råd om justering

- Start med `-j` sat til halvdelen af antallet af fysiske kerner, og øg værdien, indtil forbedringerne udebliver.
- Ved søgning udelukkende efter bogstavelige faste strenge i små repositories er kørsel i én proces som regel hurtigere end enhver parallel konfiguration.
- Ingen offentliggjorte benchmarks måler parallel AST-søgning eller -omskrivning. Mål på dit eget træ, før du vælger antal job.
- Rækkerne »Scan Mode: Parallel Text« i README (`1`, `2` og `4` workers på datasættet WordPress) måler ikke puljen: de søger efter den korte bogstavelige streng `function`, hvis tærskel på `jobs * 4_000` filer er større end datasættet. Derfor køres alle rækker i samme proces ([#8](https://github.com/inline0/greph/issues/8)).

## Begrænsninger

- Den aktuelle pulje understøtter ikke work stealing. Hvis en del er betydeligt tungere end de andre, venter puljen på den langsomste worker.
- Worker-resultaterne buffres, indtil alle workers er færdige. Streaming af output fra en langvarig scanning (som `rg --json` streamer hændelser) understøttes ikke i parallel tilstand.
- Forældreprocessen sorterer resultaterne igen efter sammenfletning, så worker-puljen reducerer ikke det maksimale hukommelsesforbrug sammenlignet med scanning i én proces.

Disse begrænsninger er acceptable for de arbejdsbelastninger, Greph er beregnet til (interaktiv kodesøgning, agentforløb og CI-jobs på øjebliksbilleder). De bliver taget op igen, hvis profilering viser, at de er en flaskehals på virkelige datasæt.
