preface

Under the traditional PHP LNMP architecture, some problems have always bothered us. Due to the serial execution of PHP programs, in IO intensive applications, PHP programs can only execute the subsequent code after the IO operation is completed, and most of the time is spent waiting for IO, seriously affecting the execution efficiency, which is very unreasonable. Now there is a scenario where an interface needs to call 10 third party Http interfaces to get all the data, assuming that each interface call takes an average of 300ms, which in traditional PHP serial mode takes 3 seconds to complete. Using a Swoole-based coroutine Http client can solve this problem, enabling concurrent invocation of Http requests.

practice

Below, we use the traditional Http client and Swoole coroutine client to make a comparison. By comparing the total response time of requests to taobao home page for N consecutive times, we can intuitively see the advantages of concurrent calls.

Example of a traditional Http client

$start = microtime(true);
$n = 50;
for ($i = 0; $i < $n; $i++) {
    $http = new Http();
    $res = $http->get('https://www.taobao.com/');
    $res->getBody()->getContents();
}
$end = microtime(true);
echo bcsub($end,$start,2).PHP_EOL;
Copy the code

Swoole coroutine Http client example

go(function (a){
    $start = microtime(true);
    // Request n concurrently
    $result = [];
    $clients = [];
    $n = 50;
    for ($i = 0; $i < $n; $i++) {
        $cli = new \Swoole\Coroutine\Http\Client('www.taobao.com'.443.true);
        $cli->setHeaders([
            'Host'= >"www.taobao.com"."User-Agent"= >'the Chrome / 49.0.2587.3'.'Accept'= >'text/html,application/xhtml+xml,application/xml'.'Accept-Encoding'= >'gzip',]); $cli->set(['timeout'= >2]);
        $cli->setDefer();
        $cli->get('/');
        $clients[] = $cli;
    }

    for ($i = 0; $i < $n; $i++) {
        if(! $clients[$i]->recv()) {continue;
        }

        $result[] = $clients[$i]->body;
    }

    $end = microtime(true);
    echo bcsub($end,$start,2).PHP_EOL;
});
Copy the code

The data analysis

Call the number Response time (coroutine) Response time (traditional)
10 1.09 s 3.64 s
20 2.33 s 7.27 s
30 2.89 s 14.91 s
50 3.96 s 17.57 s
100 7.33 s 37.23 s

As can be seen from the above data, the speed of the coroutine mode is several times that of the traditional mode, and the speed advantage of the coroutine mode becomes more and more obvious as the number of calls increases, which is a huge performance improvement brought by the asynchronous mode in IO intensive scenarios.

Serial call, concurrent call diagram

conclusion

If, like me, you’re stuck in an IO – intensive scenario where you can’t get a qualitative speed boost no matter how optimized you are, you can try Swoole’s coroutine mode, which may have unexpected results. In most Web scenarios, it is not our program execution is slow, but most of the time waiting for I/O to end, no matter how to optimize the code improvement is not obvious, it is better to change the idea and use coroutine asynchrony to solve the PROBLEM of I/O waiting, the improvement is huge. Hope you found this article helpful!