Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ For this reason, we have written this plugin, which — in addition to addressin
- [php_namespace](#php_namespace)
- [src_path](#src_path)
- [grpc](#grpc)
- [memory limit](#memory-limit)
- [multiple options](#multiple-options)
- [Generated code guide](#generated-code-guide)
- [numbers](#numbers)
Expand Down Expand Up @@ -170,6 +171,32 @@ protoc \

To generate only the server code, use `grpc=server`. By default, and when passing `grpc=client,grpc=server`, both the client and server will be generated.

### `memory limit`

When processing very large schemas, the default PHP `memory_limit` (often `128M`) may be insufficient and lead to plugin exit code `255`.

The plugin now ensures at least `512M` by default. If you need a different value, override it with the `THESIS_PLUGIN_MEMORY_LIMIT` environment variable.

When using a locally installed plugin:
```shell
THESIS_PLUGIN_MEMORY_LIMIT=1G protoc \
--plugin=protoc-gen-php-plugin=/usr/local/bin/protoc-gen-php \
protos/*.proto \
--php-plugin_out=genproto
```

When using the Docker image:
```shell
docker run --rm \
--user $(id -u):$(id -g) \
-e THESIS_PLUGIN_MEMORY_LIMIT=1G \
-v "$(PWD):/workspace" \
-w /workspace \
ghcr.io/thesis-php/protoc-plugin:latest \
--php-plugin_out=genproto \
protos/*.proto
```

### Multiple options

You can pass multiple options separated by commas. For example, if you want to specify a different namespace, place all the code in the root directory, and generate only the `gRPC` client, you can write the following:
Expand Down
11 changes: 11 additions & 0 deletions bin/compiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@

require_once __DIR__ . '/../vendor/autoload.php';

if (is_string($configuredMemoryLimit = getenv('THESIS_PLUGIN_MEMORY_LIMIT'))) {
@ini_set('memory_limit', $configuredMemoryLimit);
} else {
$memoryLimitBytes = ini_parse_quantity(ini_get('memory_limit'));

// We should increase memory_limit if it is lower than 512M.
if ($memoryLimitBytes !== -1 && $memoryLimitBytes < 512 * 1_024 * 1_024) {
@ini_set('memory_limit', '512M');
}
}

use Thesis\Protobuf\Decoder;
use Thesis\Protobuf\Encoder;
use Thesis\Protoc;
Expand Down
67 changes: 67 additions & 0 deletions tests/CompilerMemoryLimitTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

declare(strict_types=1);

namespace Thesis\Protoc;

use PHPUnit\Framework\Attributes\CoversNothing;
use PHPUnit\Framework\TestCase;

#[CoversNothing]
final class CompilerMemoryLimitTest extends TestCase
{
public function testCompilerUsesMemoryLimitFromEnvironment(): void
{
$memoryLimit = self::runCompilerScript(
initialMemoryLimit: '64M',
envMemoryLimit: '1G',
);

self::assertSame('1G', $memoryLimit);
}

public function testCompilerRaisesDefaultMemoryLimitTo512M(): void
{
$memoryLimit = self::runCompilerScript(
initialMemoryLimit: '64M',
);

self::assertSame('512M', $memoryLimit);
}

private static function runCompilerScript(string $initialMemoryLimit, ?string $envMemoryLimit = null): string
{
$code = <<<'PHP'
require 'bin/compiler.php';
fwrite(STDERR, "\nMEMORY_LIMIT=" . ini_get('memory_limit') . "\n");
PHP;

$process = proc_open(
[PHP_BINARY, '-d', "memory_limit={$initialMemoryLimit}", '-r', $code],
[
0 => ['file', '/dev/null', 'r'],
1 => ['file', '/dev/null', 'w'],
2 => ['pipe', 'w'],
],
$pipes,
\dirname(__DIR__),
$envMemoryLimit !== null
? ['THESIS_PLUGIN_MEMORY_LIMIT' => $envMemoryLimit]
: [],
);

self::assertIsResource($process);
self::assertArrayHasKey(2, $pipes);

$stderr = stream_get_contents($pipes[2]);
fclose($pipes[2]);
self::assertIsString($stderr);

self::assertSame(0, proc_close($process), $stderr);

self::assertMatchesRegularExpression('/MEMORY_LIMIT=(.+)\n/', $stderr);
preg_match('/MEMORY_LIMIT=(.+)\n/', $stderr, $matches);

return trim($matches[1] ?? '');
}
}