From bbf33b836026cbe9fb9e7c76291dcb133b7144e2 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Mon, 10 Aug 2026 00:57:19 +0900 Subject: feat(xdebug): switch Xdebug off in the PHP worker Composer restarts itself with Xdebug unloaded because Xdebug makes PHP several times slower. Xdebug is never loaded into this process, so what needs dealing with is the PHP worker: it is spawned with `-d xdebug.mode=off` and `XDEBUG_MODE=off` (Xdebug reads the environment variable first and lets it override every ini setting), which makes its module init return before it installs any executor, compile, error or opcode hook. Rewriting the ini files and re-executing, the way xdebug-handler does, would additionally cover Xdebug 2, which hooks unconditionally and has no equivalent setting. That is not worth its machinery here: Xdebug 2 caps out at PHP 7.4, while every PHP version Composer supports can run Xdebug 3. What remains of XdebugHandler is small enough to live beside the worker it governs, so its crate is gone and its callers inline it. isXdebugActive answers false without asking PHP whenever the worker is switched off, so a command that needs no PHP does not spawn one just for the Xdebug warning; diagnose reports what the worker measures instead, which still surfaces an Xdebug that ignores the setting. PlatformRepository has no unloaded extension to restore, since switching the mode off leaves it loaded. COMPOSER_ORIGINAL_INIS is neither written nor read: it exists so a restarted process can name the ini files it replaced, and IniHelper can report the worker's own. IniHelperTest injects through that variable, so none of its cases are ported. Co-Authored-By: Claude Opus 5 (1M context) --- docs/dev/php-rpc.md | 3 ++- docs/dev/xdebug.md | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 docs/dev/xdebug.md (limited to 'docs/dev') diff --git a/docs/dev/php-rpc.md b/docs/dev/php-rpc.md index 314386d8..8418db88 100644 --- a/docs/dev/php-rpc.md +++ b/docs/dev/php-rpc.md @@ -11,7 +11,8 @@ domain socket. There is exactly one child process per Shirabe process, shared by The existing `PhpExecutableFinder` class resolves the PHP binary. The child is started with `-d serialize_precision=-1` so the wire codec's float formatting is pinned to the default PHP -behavior. +behavior, and with `-d xdebug.mode=off` unless `COMPOSER_ALLOW_XDEBUG` asks for Xdebug to stay +(see `xdebug.md`). ## Transport diff --git a/docs/dev/xdebug.md b/docs/dev/xdebug.md new file mode 100644 index 00000000..be198cca --- /dev/null +++ b/docs/dev/xdebug.md @@ -0,0 +1,28 @@ +# Xdebug + +Composer restarts itself without Xdebug loaded, because Xdebug makes PHP +several times slower. Shirabe is written in Rust, where Xdebug does not exist, +but it invokes a PHP command for plugins, scripts and platform queries. +When Shirabe spawns a PHP worker, Xdebug is disabled as Composer does. + +The PHP worker is spawned with the `-d xdebug.mode=off` flag and the +`XDEBUG_MODE=off` environment variable. The way to disable Xdebug in Shirabe is +different from Composer: Composer restarts its own process with a temporary +INI file, where Xdebug extension is disabled. The difference probably does not +matter, both for users and for plugin authors. + +## Enable Xdebug in Shirabe's PHP worker + +It is the same as Composer: setting `COMPOSER_ALLOW_XDEBUG` to 1 makes Shirabe +leave Xdebug enabled. + +``` +$ COMPOSER_ALLOW_XDEBUG=1 shirabe install +``` + +## Xdebug 2 support + +Shirabe does not try to disable Xdebug version 2 because Xdebug 2 has no +`xdebug.mode` or `XDEBUG_MODE`, while Composer disables Xdebug 2 too. The +performance penalty seems to be small as Shirabe's CPU-heavy workloads are +written in Rust. -- cgit v1.3.1-4-g156e