Often the fix is to move work out of the request: it queues a job and returns, and a worker sends the mail. Laravel 2,157 's queues are Queues and Scheduling, cron is Cron, Logs and journalctl and supervising workers is Processes and Monitoring. A CLI worker can also start processes itself:
<?php
$t0 = hrtime(true);
foreach (['resize' => 0.3, 'email' => 0.2, 'report' => 0.4] as $job => $secs) {
$pid = pcntl_fork();
if ($pid === 0) { usleep((int) ($secs * 1e6)); exit(0); } // child: one job, then exit
$kids[$pid] = $job; // parent: remember who does what
}
while ($kids) {
$pid = pcntl_wait($status); // blocks until any child exits
printf("%.2f s %s exited %d\n", (hrtime(true) - $t0) / 1e9, $kids[$pid],
pcntl_wexitstatus($status));
unset($kids[$pid]);
}
$proc = proc_open(['sh', '-c', 'sort | uniq -c | sort -rn'], [['pipe', 'r'], ['pipe', 'w']],
$io); // argv array: no shell quoting
fwrite($io[0], "php\nmysql\nphp\nphp\n") && fclose($io[0]); // EOF lets sort answer
echo stream_get_contents($io[1]), 'exit code ', proc_close($proc), "\n";Output
0.22 s email exited 0
0.32 s resize exited 0
0.42 s report exited 0
3 php
1 mysql
exit code 0pcntl_fork() returns 0 in the child and its PID in the parent. The jobs ran in parallel and were reaped as they finished. Reconnect to MySQL 524 in each child, since connections are inherited. The parallel extension (1.2.15) adds threads but needs a ZTS build; Ubuntu 225 's PHP is NTS.