
# Procesos de trabajo paralelos

Greph distribuye los análisis de texto y AST entre varios procesos de trabajo cuando el volumen justifica el coste adicional. El grupo se basa en `pcntl_fork()` y recurre a la ejecución dentro del proceso cuando `ext-pcntl` no está disponible (Windows, algunos entornos PaaS y alojamientos restringidos).

## Activar análisis paralelos

Defina `-j N` en CLI o `jobs: N` en el objeto de opciones correspondiente:

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

## Cuándo se activa el procesamiento paralelo

Greph no paraleliza todas las tareas. Crear N procesos y enviar sus resultados de ida y vuelta por tuberías tiene un coste; con listas pequeñas de archivos, ese coste supera el de la búsqueda. En su lugar, la fachada calcula un umbral según el número de tareas, el modo de búsqueda y la forma del patrón. Solo se envían al grupo las listas de archivos que superan el umbral.

Las heurísticas actuales (en `Greph\Greph::shouldUseTextWorkers` y elementos relacionados):

- Las ejecuciones de una sola tarea (`-j 1`) siempre se realizan dentro del proceso.
- Los análisis de texto predeterminados requieren aproximadamente `jobs * 2_000` archivos para activar el grupo.
- Los modos de recuento, archivos con coincidencias y archivos sin coincidencias reducen el umbral a aproximadamente `jobs * 750` porque el trabajo por archivo es menor.
- Los patrones de cadena fija cortos con forma de identificador elevan el umbral a aproximadamente `jobs * 4_000`, ya que la ruta rápida de búsqueda literal ya es tan barata que rara vez compensa crear procesos.
- La búsqueda y reescritura de AST usan el umbral `jobs * 750`.

Estas cifras son heurísticas, no garantías. Se ajustan con el corpus de pruebas de rendimiento WordPress y pueden revisarse.

## Cómo funciona el grupo

`Greph\Parallel\WorkSplitter` distribuye la lista de archivos en N fragmentos. `Greph\Parallel\WorkerPool` crea un proceso de trabajo por fragmento; cada proceso ejecuta la misma función en su parte, y `Greph\Parallel\ResultCollector` lee los resultados serializados mediante un par de sockets Unix por proceso. El proceso principal espera a que terminen todos y luego combina y vuelve a ordenar los resultados para que el orden de salida sea estable, independientemente de cómo se haya dividido el trabajo.

En el modo de texto, el grupo de procesos usa un códec personalizado para la transmisión (`Greph\Text\TextResultCodec`) que mantiene compacto el contenido serializado. El modo AST usa el `serialize()` estándar de PHP.

## Cuando pcntl no está disponible

Si no se puede llamar a `pcntl_fork` (Windows, compilaciones reforzadas de PHP), el grupo recurre de forma transparente a ejecutar cada fragmento dentro del proceso. El resultado es el mismo que con `-j 1`. Greph no genera ningún error; simplemente se ejecuta con un solo proceso.

Puede detectarlo durante la ejecución comprobando `function_exists('pcntl_fork')`.

## Consejos de ajuste

- Empiece con `-j` establecido en la mitad del número de núcleos físicos y auméntelo hasta que dejen de mejorar los resultados.
- Para búsquedas de cadenas fijas que solo usan literales en repositorios pequeños, un solo proceso suele ser más rápido que cualquier configuración paralela.
- Ninguna prueba de rendimiento publicada mide la búsqueda o reescritura de AST en paralelo. Mida el rendimiento en su propio árbol antes de elegir el número de tareas.
- Las filas «Modo de análisis: texto paralelo» de README (`1`, `2` y `4` procesos de trabajo en el corpus WordPress) no miden el grupo: buscan el literal corto `function`, cuyo umbral de `jobs * 4_000` archivos supera el tamaño del corpus, así que todas las filas se ejecutan dentro de un solo proceso ([#8](https://github.com/inline0/greph/issues/8)).

## Limitaciones

- El grupo actual no admite el robo de trabajo. Si un fragmento tiene mucha más carga que los demás, el grupo espera al proceso más lento.
- Los resultados de los procesos de trabajo se almacenan en búfer hasta que todos terminan. El modo paralelo no admite la salida en flujo de un análisis prolongado (como la transmisión de eventos de `rg --json`).
- El proceso principal vuelve a ordenar los resultados después de combinarlos, por lo que el grupo no reduce el uso máximo de memoria frente a un análisis de un solo proceso.

Estas limitaciones son aceptables para las cargas de trabajo a las que apunta Greph (búsqueda interactiva de código, ciclos de agentes y trabajos de CI sobre instantáneas). Se revisarán si el perfilado muestra que son un cuello de botella en corpus reales.
