php-http / curl-client

cURL client
http://httplug.io
MIT License
445 stars 28 forks source link

CurlMutlirunner burn CPU #55

Open jderusse opened 5 years ago

jderusse commented 5 years ago

given the following snippet

#!/usr/bin/env php
<?php

require_once "vendor/autoload.php";

use Http\Client\Curl\Client;
use Http\Discovery\MessageFactoryDiscovery;
use Http\Discovery\StreamFactoryDiscovery;
$messageFactory = MessageFactoryDiscovery::find();
$client = new Client($messageFactory, StreamFactoryDiscovery::find());

$client->sendAsyncRequest(
    $messageFactory->createRequest('GET', 'https://httpstat.us/200?sleep=3000')
)->wait(true)->getBody()->getContents();

the service" https://httpstat.us/200?sleep=3000 simulate a slow request waiting for 3 seconds.

Where running the script, my application consume A LOT of CPU while waiting for the request

$ time ./index.php                                                                                                                                                                                                                                                                                
real    0m3.190s
user    0m1.638s
sys     0m1.523s

Here CPU is used 1.638s + 1.523s = 3.161s to process this 3.190s script

when applying this durty patch

diff --git a/src/MultiRunner.php b/src/MultiRunner.php
index 545f39a..5872804 100644
--- a/src/MultiRunner.php
+++ b/src/MultiRunner.php
@@ -82,6 +82,7 @@ class MultiRunner
     public function wait(PromiseCore $targetCore = null)
     {
         do {
+            usleep(1);
             $status = curl_multi_exec($this->multiHandle, $active);
             $info = curl_multi_info_read($this->multiHandle);
             if (false !== $info) {

I get

$ time ./index.php
real    0m3.163s
user    0m0.234s
sys     0m0.211s

now, the CPU is used 0.445s to process the same request.

mekras commented 5 years ago

I'll check this today.

joelwurtz commented 5 years ago

Why there is no curl_multi_select ? Burning cpu seems to be normal here since we never wait for any activity and loop until something happens.

I think adding a simple curl_multi_select($this->multiHandle); after curl_multi_exec will do the trick

mekras commented 5 years ago

@jderusse, can you try changed version from branch https://github.com/php-http/curl-client/tree/issue-55-CurlMultirunner_burn_CPU ?

mekras commented 5 years ago

@jderusse, I've update branch. Can you check it?

jderusse commented 5 years ago

Would you mind to open a PR @mekras ? It would be easier to review :-)