
# Paralēlie darbinieki

Greph sadala teksta un AST skenēšanas pa darbinieku kopumu, ja darba apjoms attaisno papildu izmaksas. Kopums izmanto `pcntl_fork()` un pāriet uz izpildi pašreizējā procesā, ja `ext-pcntl` nav pieejams (Windows, dažās PaaS vidēs vai ierobežotā mitināšanas vidē).

## Paralēlo skenēšanu iespējošana

Iestatiet `-j N` uz CLI vai `jobs: N` attiecīgajā opciju 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),
);
```

## Kad sākas paralēlā izpilde

Greph neizpilda paralēli katrā gadījumā. N procesu palaišana un to rezultātu pārsūtīšana turp un atpakaļ pa caurulēm rada papildu izmaksas, kas nelielos failu sarakstos pārsniedz pašas meklēšanas izmaksas. Tāpēc fasāde aprēķina slieksni, ņemot vērā uzdevumu skaitu, meklēšanas režīmu un veidnes formu. Darbinieku kopumam tiek nodoti tikai tie failu saraksti, kas pārsniedz slieksni.

Pašreizējā heuristika (failā `Greph\Greph::shouldUseTextWorkers` un saistītajos failos):

- Ar vienu uzdevumu (`-j 1`) vienmēr strādā pašreizējā procesā.
- Noklusējuma teksta skenēšanai vajadzīgi aptuveni `jobs * 2_000` faili, lai tiktu ieslēgts darbinieku kopums.
- Skaita, failu ar atbilstībām un failu bez atbilstībām režīmos slieksnis samazinās līdz aptuveni `jobs * 750`, jo darbs katram failam ir lētāks.
- Īsām, identifikatoriem līdzīgām fiksētām virknēm slieksnis palielinās līdz aptuveni `jobs * 4_000`, jo ātrais burtisko virkņu ceļš jau ir tik lēts, ka paralēla izpilde reti atmaksājas.
- AST meklēšanai un AST pārrakstīšanai tiek izmantots `jobs * 750` slieksnis.

Šie skaitļi ir aptuvenas vērtības, nevis garantijas. Tie ir pielāgoti WordPress veiktspējas testu datu kopai un var tikt pārskatīti.

## Kā darbojas kopums

`Greph\Parallel\WorkSplitter` sadala failu sarakstu N daļās. `Greph\Parallel\WorkerPool` izveido pa vienam darbinieka procesam katrai daļai; katrs darbinieks palaiž to pašu funkciju savā saraksta daļā, un `Greph\Parallel\ResultCollector` nolasa serializētos rezultātus pa Unix ligzdu pāri katram darbiniekam. Vecākprocess sagaida visus darbiniekus, pēc tam apvieno un kārto rezultātus, lai izvades secība būtu nemainīga neatkarīgi no darba sadalījuma.

Teksta režīmā darbinieku kopums izmanto pielāgotu pārraides kodeku (`Greph\Text\TextResultCodec`), lai serializētā datu plūsma būtu kompakta. AST režīmā izmanto PHP standarta `serialize()`.

## Ja pcntl nav pieejams

Ja `pcntl_fork` nav izsaucams (Windows, ierobežotas PHP versijas), darbinieku kopums nemanāmi pāriet uz katras daļas izpildi pašreizējā procesā. Rezultāts ir tāds pats kā ar `-j 1`. Greph nerada kļūdu; tas vienkārši darbojas vienā pavedienā.

To var noteikt izpildes laikā, pārbaudot `function_exists('pcntl_fork')`.

## Ieteikumi pielāgošanai

- Sāciet ar `-j`, kas iestatīts uz pusi no fizisko kodolu skaita, un palieliniet to, līdz vairs nav uzlabojumu.
- Meklējot tikai burtiskas virknes nelielos repozitorijos, viena procesa režīms parasti ir ātrāks par jebkuru paralēlo konfigurāciju.
- Nav publicētu etalonmērījumu, kas novērtētu paralēlu AST meklēšanu vai pārrakstīšanu. Pirms izvēlaties uzdevumu skaitu, veiciet mērījumus savā failu kokā.
- README “Scan Mode: Parallel Text” rindās (`1`, `2` un `4` darbinieki WordPress korpusā) pūls netiek mērīts: tajās tiek meklēta īsā burtiskā virkne `function`, kuras slieksnis — `jobs * 4_000` faili — pārsniedz korpusa lielumu, tāpēc katra rinda darbojas vienā procesā ([#8](https://github.com/inline0/greph/issues/8)).

## Ierobežojumi

- Pašreizējais pūls neatbalsta darba zagšanu. Ja viens datu gabals ir daudz apjomīgāks par pārējiem, pūls gaida lēnāko darbinieku.
- Darbinieku rezultāti tiek buferēti, līdz visi darbinieki pabeidz darbu. Ilgstošas skenēšanas rezultātu straumēšana (kā notikumus straumē `rg --json`) paralēlajā režīmā netiek atbalstīta.
- Pēc rezultātu apvienošanas vecākprocess tos sakārto atkārtoti, tāpēc darbinieku pūls nesamazina maksimālo atmiņas patēriņu salīdzinājumā ar skenēšanu vienā procesā.

Šie ierobežojumi ir pieņemami darba slodzēm, kurām Greph ir paredzēts (interaktīva koda meklēšana, aģentu cikli, CI uzdevumi ar momentuzņēmumiem). Tie tiks pārskatīti, ja profilēšana parādīs, ka reālos korpusos tie kļūst par veiktspējas šaurajām vietām.
