diff --git a/README.md b/README.md index 5998c6a..079b0f8 100644 --- a/README.md +++ b/README.md @@ -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) @@ -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: diff --git a/bin/compiler.php b/bin/compiler.php index 325669e..febf52a 100755 --- a/bin/compiler.php +++ b/bin/compiler.php @@ -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; diff --git a/tests/CompilerMemoryLimitTest.php b/tests/CompilerMemoryLimitTest.php new file mode 100644 index 0000000..4f280e7 --- /dev/null +++ b/tests/CompilerMemoryLimitTest.php @@ -0,0 +1,67 @@ + ['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] ?? ''); + } +}