Sample Header Ad - 728x90

What Causes PHP Forks to Consolidate on a Single CPU Core in FreeBSD 13.3?

0 votes
1 answer
53 views
I'm using a PHP 8.x script to process a series of images, performing various conversions and resizing tasks. To make the most of the server's multiple cores, I employ the pcntl_fork() function to create child processes that can simultaneously handle different images. This means instead of processing images sequentially, each image can be processed concurrently on separate cores. For instance, if I have 10 images to process and each takes 3 seconds individually, without parallel processing, it would take a total of 30 seconds. However, with parallel processing, all 10 images can finish processing simultaneously in just 3 seconds. This approach has been effective until we updated to FreeBSD 13.3. After the update, the forked processes no longer distribute across different cores; instead, they all run on a single core. Consequently, if I have 10 forked processes running, each is constrained to using only 10% of a single core, resulting in a 10-fold increase in processing time. We've conducted tests with FreeBSD versions ranging from 9.x up to 13.2-RELEASE-p11 and found that the issue doesn't occur. Additionally, when using a 13.2 userland and temporarily booting the 13.3 kernel, the problem still doesn't manifest. However, when both the userland and kernel are updated to 13.3, the problem consistently occurs. Further tests with a fresh installation of FreeBSD 14.0 on a separate system confirm that the issue persists there as well. We've also ruled out PHP version as a factor, as testing across versions 8.0 to 8.3 yields the same results. Do you have any insights into what might be causing this issue, or suggestions for resolving it? Edit: Adding MRE code, as suggested in the comments: readImage($fullLocalImagePath); echo " → Finished reading image $i into Imagick.\n"; $imagick->setImageCompressionQuality(88); $imagick->resizeImage(4800, 4800, imagick::FILTER_LANCZOS, .9, false); $imagick->writeImage($finalImagePath); echo " → → Finished resizing and saving image $i into Imagick.\n"; $imagick->clear(); exit(0); // Exit the child process after processing the image } } // Wait for the forked processes to finish while ($childPID = pcntl_waitpid(0, $status)) { if ($childPID == -1) { // No child processes left to wait for break; } echo " → → → Child process $childPID has finished.\n"; // Handle the exit status based on the child process PID if (in_array($childPID, $forkedProcessIds)) { // Remove the child process ID from the tracking array $forkedProcessIds = array_diff($forkedProcessIds, array($childPID)); } } ?>
Asked by Adam Ellis (31 rep)
May 2, 2024, 10:21 PM
Last activity: May 8, 2024, 10:02 AM