php xdebug: How to profile forked process

前端 未结 1 1574
-上瘾入骨i
-上瘾入骨i 2020-12-14 22:45

I am running a PHP daemon to be profiled.

The started php process loads all required data, forks itself to distribute workload over all cores, waits for the forked c

相关标签:
1条回答
  • 2020-12-14 23:05

    I ran into the same issue and solved without XDebug. Unfortunately I couldn't find a way with XDebug. It's like somehow it does not care about any forked process.

    I solved by using Xhprof to profile and Xhgui to inspect the logs. Xhprof is a great tool internally developed by Facebook and then released afterwards open-source. The cool thing is that you can decide exactly when to start profiling and when to stop. This gives you the ability to work around our issue.

    So first of all let's get it installed!

    sudo pecl install xhprof-beta
    

    If you're using a debian based distro make sure you got also graphviz installed.

    sudo apt-get install graphviz
    

    Now let's take a look at the code.

    $children = [];
    
    do {
        if (count($children) < $maxConsumers) {
            $pid = pcntl_fork();
            $children[] = $pid;
    
            if ($pid == -1) {
                throw new \RuntimeException('Could not fork process');
            } else if ($pid === 0) {
                // we are the child
    
                if ($verbose) {
                    $output->writeln(sprintf('Child here (PID = %s)', posix_getpid()));
                }
    
                if ($xhProf) {
                    // here we enable xhprof thus the profiling starts
                    xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY);
                }
    
                // DO YOUR MAGIC HERE!
    
                if ($xhProf) {
                    // and here we call the xhgui header file that will
                    // stop xhprof and write all the gathered data into
                    // mongo or into a dedicated file
                    require_once('/var/www/xhgui/external/header.php');
                }
    
                exit;
            } else {
                // we are the parent
                if ($verbose) {
                    $output->writeln(sprintf('Parent here (PID = %s) spawned a new child (PID = %s)', posix_getpid(), $pid));
                }
            }
        } else {
            if ($verbose) {
                $output->writeln(sprintf("Parent - spawned enough children, let's wait them..."));
            }
    
            $deadPID = pcntl_wait($status);
            $children = array_diff($children, [$deadPID]);
    } while (true);
    
    // Waits for all remaining children
    while (($pid = pcntl_waitpid(0, $status)) != -1) {
        if ($verbose) {
            $status = pcntl_wexitstatus($status);
            $output->writeln(sprintf("Child (PID %d) terminated. Status is %s.", $pid, $status));
        }
    }
    

    In order to inspect your logs you also need to configure Xhgui properly. You'll probably need a virtual host as well.

    For all the needed configuration and for reference:

    • xhprof github page
    • xhprof php page
    • xhgui github page
    • tutorial by Davey Shafik part 1
    • tutorial by Davey Shafik part 2
    • tutorial by Davey Shafik part 3
    0 讨论(0)
提交回复
热议问题