Open-source project
krakjoe/parallel avatar
krakjoe/parallel

krakjoe/parallel: A PHP 8 Parallel Runtime

A succinct parallel concurrency API for PHP8

1,597 stars96 forksCNOASSERTION

At a glance

What is it?
krakjoe/parallel is a native PHP 8 extension that exposes a small API for running closures through `\parallel\Runtime`. It suits PHP developers who need concurrent work, but its custom licence and native extension requirements require review before adoption.
Who is it for?
krakjoe/parallel is appropriate for PHP developers who need a compact native API for running independent closures concurrently and can add and update a PHP extension. It is less suitable for Composer-only deployments, workloads that depend on undocumented serialisation rules, or organizations that cannot accept the custom `LICENSE`.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 8 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Why krakjoe/parallel Exists

krakjoe/parallel addresses a specific limitation in ordinary PHP application code: work submitted as a closure normally proceeds as part of the calling flow. The project offers a concise alternative for PHP 8 developers who want to start independent closures and collect their results later. Its stated scope is intentionally narrow. The README calls it “A succinct parallel concurrency API for PHP 8,” rather than presenting a job queue, scheduler, database of concurrent workers, or general-purpose distributed task system.

That narrowness makes its intended users easier to identify. A PHP developer may reach for it when a local operation is independent of the work that submits it and the application can tolerate a native extension. The example uses a closure that writes output and returns the string `easy`. The caller starts that closure, continues its own loop, and then asks the returned object for the result. This shape is useful when the caller has another immediate activity to perform, although the README does not document task cancellation, timeout handling, priorities, queues, or worker limits.

The repository also includes `tests/`, `src/`, `php_parallel.c`, `php_parallel.h`, and files for Unix and Windows build configuration. Based on that layout, this is a compiled PHP extension rather than a JavaScript or Python concurrency package managed entirely through application-level dependencies. The README does not identify the underlying execution resources, so it would be inaccurate to claim that every task uses a process, every task uses a thread, or that all calls have identical isolation and scheduling behavior. The PHP manual is identified as the main documentation source, while the README leaves detailed runtime guarantees outside its short example.

The Runtime and Future Data Flow

The visible API begins with `new \parallel\Runtime()`. The resulting object receives a closure through `run()`. The README example does not pass arguments directly to `run()`; it closes over nothing and generates its output inside the callable. In exchange, `run()` returns an object from which the caller later requests `value()`.

The application-side flow is submission, continued parent work, then result retrieval. In the documented example, the submitted closure prints 500 asterisks and returns `easy`. The caller prints 500 periods before reading the result. Because the README describes the output only as “something like” an interleaving of those characters, it does not promise a fixed execution order. The meaningful API guarantee shown by the example is that the return value can be obtained through `$future->value()`; it is not evidence of a particular scheduling algorithm.

The native layer is visible in `php_parallel.c`, `php_parallel.h`, and the `src/` directory. PHP extension metadata appears in `composer.json`, `config.m4`, and `config.w32`, which indicates that installation and availability are tied to PHP build and packaging concerns. The repository also carries a `Makefile.frag`, while CI configuration covers Linux and Windows and an AddressSanitizer workflow appears in the README badges.

Several engineering questions remain undocumented in the README. It does not explain which closure variables are copied into submitted work, whether referenced objects must be serializable, whether return values have type restrictions, how exceptions surface, or whether a failed callable invalidates its future. It also does not document how many closures can be outstanding or whether resource limits are configured. Those are not small implementation details for a concurrency API. An application must confirm them against the linked PHP manual or direct source review before passing stateful services, database handles, framework objects, or other resources into submitted closures.

Installing the Extension and Running the First Task

The README directs installation questions to `INSTALL.md`; it does not include an installation command. It would therefore be unsafe to invent a `pecl`, Composer, PHPize, or platform-specific command. The project documents its supported installation path in `INSTALL.md`, and that file should be checked against the PHP version, operating system, build tools, and packaging environment used by the host.

A first executable example can be copied directly from the README. Save it as a PHP file served by an installation that has the extension enabled, then execute it through that environment. The closure writes 500 asterisks and returns `easy`, while the caller writes 500 periods and prints the future value.

php
<?php
$runtime = new \parallel\Runtime();

$future = $runtime->run(function(){
    for ($i = 0; $i < 500; $i++)
        echo "*";

    return "easy";
});

for ($i = 0; $i < 500; $i++) {
    echo ".";
}

printf("\nUsing \\parallel\\Runtime is %s\n", $future->value());

The final line should print `Using \parallel\Runtime is easy`, following the example in the README. Character ordering can differ because the README presents its interleaved output only as an abbreviated possibility. If the class cannot be found, installation or enabled-extension configuration is not complete, but the README does not document a diagnostic command or configuration file. If a closure captures unsupported state or returns an unsupported value, the README provides no troubleshooting procedure. The implementation-level debugging guidance belongs in `CONTRIBUTING.md`, which the README identifies for development and debugging work.

Container-oriented contributors also have `docker-compose.yml`. Its `php` service uses `ghcr.io/krakjoe/php-${PHP_BUILD:-release}-${PHP_VERSION:-8.5}:${PHP_IMAGE_TAG:-latest}` and builds from `docker/php.dockerfile`; the `parallel` service uses `ghcr.io/krakjoe/parallel-${PHP_BUILD:-release}-${PHP_VERSION:-8.5}:${PHP_IMAGE_TAG:-latest}` and builds from `docker/parallel.dockerfile`. Those are repository development images, not an installation command stated for production hosts.

Native Extension Boundaries and Failure Cases

The principal adoption constraint is that krakjoe/parallel is not a drop-in Composer library in the repository layout. The C sources and build files indicate that deployment requires the extension to be built or delivered for the target PHP environment. Teams using immutable containers may face packaging work when the required image is unavailable. Teams that rely exclusively on pure-PHP packages cannot treat installation as ordinary application dependency resolution.

The second limitation is API depth. The README demonstrates one future-producing call and one value retrieval operation, but it does not document a scheduler control surface, structured task metadata, retry policy, failure API, timeout, cancellation, or progress reporting. This makes the extension a poor fit as the sole abstraction for a large job-processing platform that needs durable queues and operational controls. It may still fit inside a larger system that already owns those responsibilities, but that integration is not documented by the README.

State transfer is another boundary. A closure can do work and return a scalar string in the README example. The documentation does not establish support for arbitrary object graphs, resources, closures, generators, or cyclic references. Passing a service locator or framework container into a submitted closure without checking the PHP manual could therefore turn a concurrency requirement into a serialization or loading-order problem. Likewise, repeated output from the child callable should not be treated as an ordered result stream. The example allows interleaved character output and offers no protocol for collecting structured output safely.

Finally, the repository is not archived, and its last push was on 2026-10-06. Releases v1.2.13, v1.2.14, and v1.2.15 were published in May and June 2026. These facts show recent repository activity, but they do not remove upgrade work. The C extension must be checked for compatibility with the PHP version used by each application. Upgrade testing should include closure state handling, result retrieval, failure behavior, and the host packaging pipeline rather than relying only on release availability.

The Custom Licence and Upgrade Surface

GitHub classifies krakjoe/parallel as using a custom licence that it cannot map to one of its standard categories. The repository contains a `LICENSE` file, but its terms are not quoted in the README. This review cannot therefore state whether modification, redistribution, internal deployment, or commercial use carries particular conditions. That is not a reason to avoid the project automatically, but it is a required legal review item.

For engineering planning, the licence question and the upgrade path are separate. The upgrade path is visible in the recent tagged releases and the native source layout. A host may need to rebuild the extension against each PHP runtime it supports, then rebuild or deploy its application container. The repository's `docker-compose.yml` defines separate `php` and `parallel` development services, which reflects the need to coordinate extension and runtime environments. It does not prove how a production release should be packaged.

The custom licence should be read before source is copied into a distribution image, embedded in a commercial product, or offered as part of a managed service. This article does not interpret the licence. It also does not claim that later releases preserve compatibility with older PHP 8 releases, because the README states PHP 8 as the target but does not provide a compatibility matrix. The concrete maintenance question is therefore whether the available release can be built for every PHP minor version still used by the adopting organization.

When Sequential PHP or Application-Level Concurrency Is Better

The clearest alternative is ordinary sequential PHP execution when operations are short, results are needed immediately, or deployment cannot include a native extension. Sequential code has less state-transfer risk because the application does not submit closure state to another execution context. It also avoids introducing another concurrency mechanism for a workload that fits comfortably within the existing request. The trade-off is direct: the application does not gain the opportunity represented by the `Runtime` example to continue parent-side work while a submitted closure proceeds.

Another valid choice is to keep concurrency outside the PHP request, using an existing job or messaging boundary in the application architecture. The README does not document such integration, and it does not establish that this extension should handle distributed jobs. Its visible design is local to an object created by PHP application code. If requirements include durable task storage, process-level isolation across requests, retries, or operational queues, the documented krakjoe/parallel surface is too incomplete to establish suitability.

krakjoe/parallel is therefore most compelling for a narrowly scoped PHP use case that benefits from concurrent closures, accepts native extension management, and can tolerate the constraints the PHP manual defines. Sequential PHP is the better fit when extension deployment is undesirable or the task is too small to justify concurrency. The decision should begin with the PHP version and closure data crossing the API boundary, not with the abbreviated interleaved output example.

Editorial conclusion

krakjoe/parallel is appropriate for PHP developers who need a compact native API for running independent closures concurrently and can add and update a PHP extension. It is less suitable for Composer-only deployments, workloads that depend on undocumented serialisation rules, or organizations that cannot accept the custom `LICENSE`. Before adoption, inspect `LICENSE`, check the extension build requirements in `INSTALL.md`, and confirm that every closure and its captured data can cross the runtime boundary.

Frequently asked questions

What is krakjoe/parallel used for?

It provides a succinct parallel concurrency API for PHP 8. The documented example submits a closure to `\parallel\Runtime`, performs work in the caller, and retrieves the closure's return value from a future.

How do I install krakjoe/parallel for PHP 8?

The README directs users to `INSTALL.md` for installation instructions. The README does not include the contents of that file, so it does not provide a confirmed package command or build procedure.

How do I retrieve the result of a closure run with krakjoe/parallel?

Assign the object returned by `$runtime->run(...)` and call `value()` on it. In the README example, that future returns the string `easy`.

Official sources

  1. Issues
  2. krakjoe/parallel on GitHub
  3. README
  4. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/krakjoe-parallel.svg)](https://hysenlabs.com/projects/krakjoe-parallel)

Was this useful?