Ga naar de inhoud

Parallelle workers

Greph verdeelt tekst- en AST-scans over een workerpool wanneer de hoeveelheid werk groot genoeg is om de extra overhead te rechtvaardigen. De pool is gebouwd op pcntl_fork() en valt terug op uitvoering binnen hetzelfde proces wanneer ext-pcntl niet beschikbaar is (Windows, sommige PaaS-omgevingen en hosting met beperkingen).

Parallelle scans inschakelen

Stel -j N in op CLI of jobs: N in het relevante optiesobject:

Shell
./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),
);

Wanneer parallel verwerken begint

Greph paralleliseert niet onvoorwaardelijk. Het starten van N processen en het via pipes heen en weer sturen van hun resultaten brengt overhead met zich mee. Bij kleine bestandenlijsten weegt die overhead zwaarder dan het zoeken zelf. Daarom berekent de facade een drempel op basis van het aantal taken, de zoekmodus en de vorm van het patroon. Alleen bestandenlijsten boven die drempel worden naar de workerpool gestuurd.

De huidige heuristieken (in Greph\Greph::shouldUseTextWorkers en verwante onderdelen):

  • Runs met één taak (-j 1) worden altijd binnen hetzelfde proces uitgevoerd.
  • Standaardtek scans vereisen ongeveer jobs * 2_000 bestanden voordat de pool wordt ingeschakeld.
  • De modi tellen, bestanden met overeenkomsten en bestanden zonder overeenkomsten verlagen de drempel tot ongeveer jobs * 750, omdat het werk per bestand goedkoper is.
  • Korte patronen met vaste tekenreeksen die op een identifier lijken, verhogen de drempel tot ongeveer jobs * 4_000, omdat het letterlijke snelle pad al zo goedkoop is dat het starten van processen zelden voordeel oplevert.
  • AST-zoeken en AST-herschrijven gebruiken de drempel jobs * 750.

Dit zijn heuristieken, geen garanties. Ze zijn afgestemd op het benchmarkcorpus WordPress en kunnen opnieuw worden bekeken.

Hoe de pool werkt

Greph\Parallel\WorkSplitter verdeelt de bestandenlijst over N chunks. Greph\Parallel\WorkerPool start één workerproces per chunk. Elke worker voert dezelfde closure uit op zijn deel, waarna Greph\Parallel\ResultCollector de geserialiseerde resultaten via één Unix-socketpaar per worker terugleest. Het hoofdproces wacht op alle workers en voegt de resultaten daarna samen en sorteert ze opnieuw, zodat de uitvoervolgorde stabiel blijft, ongeacht hoe het werk is verdeeld.

Voor de tekstmodus gebruikt de workerpool een aangepaste codec voor verzending over de verbinding (Greph\Text\TextResultCodec) om de geserialiseerde payload compact te houden. De AST-modus gebruikt de standaard-serialize() van PHP.

Wanneer pcntl niet beschikbaar is

Als pcntl_fork niet kan worden aangeroepen (Windows, builds met een versterkte beveiliging van PHP), valt de pool transparant terug op uitvoering van elk chunk binnen hetzelfde proces. Het resultaat is hetzelfde als bij -j 1. Greph geeft geen foutmelding; het voert alles gewoon in één thread uit.

U kunt dit tijdens runtime detecteren door function_exists('pcntl_fork') te controleren.

Tips voor afstemming

  • Begin met -j ingesteld op de helft van het aantal fysieke cores en verhoog de waarde totdat u geen verbeteringen meer ziet.
  • Voor zoekopdrachten met alleen letterlijke vaste tekenreeksen in kleine repositories is één proces doorgaans sneller dan elke parallelle configuratie.
  • Er is geen gepubliceerd benchmarkrapport voor parallel AST-zoeken of -herschrijven. Meet het op uw eigen boom voordat u een aantal taken kiest.
  • De rijen 'Scanmodus: parallelle tekst' in README (1, 2 en 4 workers op het corpus WordPress) meten de pool niet: ze zoeken naar de korte literal function, waarvoor de drempel van jobs * 4_000 bestanden groter is dan het corpus. Daarom wordt elke rij binnen één proces uitgevoerd (#8).

Beperkingen

  • De huidige pool ondersteunt geen work-stealing. Als één chunk veel zwaarder is dan de andere, wacht de pool op de langzaamste worker.
  • Workerresultaten worden gebufferd totdat alle workers klaar zijn. Parallelle modus ondersteunt geen uitvoerstream voor een langlopende scan (zoals rg --json gebeurtenissen streamt).
  • Na het samenvoegen sorteert het hoofdproces de resultaten opnieuw. Daarom vermindert de workerpool het piekgeheugenverbruik niet ten opzichte van een scan met één proces.

Deze beperkingen zijn aanvaardbaar voor de werklasten waarop Greph is gericht: interactief zoeken in code, agentloops en CI-jobs op snapshots. We bekijken ze opnieuw als profilering laat zien dat ze een knelpunt vormen bij corpora uit de praktijk.