❌

Normal view

PHP CLI workers don’t share opcache, so I made them: 70–80% less memory for Laravel queues

PHP's CLI doesn't share opcache between separately started processes, so every long-running worker compiles your whole app into its own private memory. With 8 Laravel queue workers that's 8 copies of the same compiled code, often 50–80 MB each.

I built queue-prefork to fix that for Laravel's queue:work and Horizon:

  • A small template process starts with opcache and no app code.
  • Each worker is forked from it with pcntl_fork() and then boots the app itself from the normal artisan entry. So nothing booted is inherited: no DB or Redis connections, sockets, singletons or RNG state. Only the compiled code is shared, through opcache's shared memory.
  • The pid your process manager started stays (a tiny /bin/sh stub for queue:work), so supervisord or systemd signals, timeouts and restarts behave as before.

Side-by-side benchmark, two identical Docker stacks on the same job stream, Laravel 13 with ~45 packages, 1 h each:

Setup Stock Prefork
8 × queue:work, typical jobs 645 MB 192 MB (−70%)
8 × queue:work, idle 455 MB 102 MB (−78%)
8 × queue:work, heavy jobs 1,025 MB 524 MB (−49%)
Horizon, 6 supervisors 1,279 MB 240 MB (−81%)

Same throughput, 0 failed jobs, and less CPU, since new workers don't recompile anything. If any safety check fails, workers run as stock and the package tells you why.

Linux only for production; Laravel 11–13. MIT: https://github.com/tevkert/queue-prefork

Happy to answer questions about the fork and opcache side.

submitted by /u/Tevkert to r/PHP
[link] [comments]
❌