web-dev-qa-db-fra.com

Réutilisation de la même poignée de boucle. Grande augmentation des performances?

Dans un script php, je fais beaucoup de requêtes GET cUrl différentes (une centaine) vers différentes URL.

La réutilisation de la même poignée curl de curl_init améliorera-t-elle les performances ou est-elle négligeable par rapport au temps de réponse des requêtes cURL?

Je demande cela parce que dans l'architecture actuelle, il ne serait pas facile de conserver la même poignée cUrl.

Merci,

Benjamin

31
benjisail

Cela dépend si les URL sont sur les mêmes serveurs ou non. Si tel est le cas, les demandes simultanées adressées au même serveur réutilisent la connexion. voir CURLOPT_FORBID_REUSE.

Si les URL sont parfois sur le même serveur, vous devez trier les URL car le cache de connexion par défaut est limité à dix ou vingt connexions.

S'ils se trouvent sur des serveurs différents, il n'y a aucun avantage de vitesse à utiliser la même poignée.

Avec curl_multi_exec, vous pouvez vous connecter à différents serveurs en même temps (parallèle). Même alors, vous avez besoin d'une file d'attente pour ne pas utiliser des milliers de connexions simultanées.

Crossposted from Dois-je fermer cURL ou non? parce que je pense que c'est pertinent ici aussi.

J'ai essayé de mettre en boucle curl en utilisant une nouvelle poignée pour chaque demande et en utilisant la même poignée avec le code suivant:

ob_start(); //Trying to avoid setting as many curl options as possible
$start_time = microtime(true);
for ($i = 0; $i < 100; ++$i) {
    $Rand = Rand();
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, "http://www.google.com/?rand=" . $Rand);
    curl_exec($ch);
    curl_close($ch);
}
$end_time = microtime(true);
ob_end_clean();
echo 'Curl without handle reuse: ' . ($end_time - $start_time) . '<br>';

ob_start(); //Trying to avoid setting as many curl options as possible
$start_time = microtime(true);
$ch = curl_init();
for ($i = 0; $i < 100; ++$i) {
    $Rand = Rand();
    curl_setopt($ch, CURLOPT_URL, "http://www.google.com/?rand=" . $Rand);
    curl_exec($ch);
}
curl_close($ch);
$end_time = microtime(true);
ob_end_clean();
echo 'Curl with handle reuse: ' . ($end_time - $start_time) . '<br>';

et a obtenu les résultats suivants:

Curl sans réutilisation de la poignée: 8.5690529346466
Boucle avec réutilisation de la poignée: 5.3703031539917

Ainsi, la réutilisation de la même poignée fournit en fait une augmentation substantielle des performances lors de la connexion au même serveur plusieurs fois. J'ai essayé de me connecter à différents serveurs:

$url_arr = array(
    'http://www.google.com/',
    'http://www.bing.com/',
    'http://www.yahoo.com/',
    'http://www.slashdot.org/',
    'http://www.stackoverflow.com/',
    'http://github.com/',
    'http://www.harvard.edu/',
    'http://www.gamefaqs.com/',
    'http://www.mangaupdates.com/',
    'http://www.cnn.com/'
);
ob_start(); //Trying to avoid setting as many curl options as possible
$start_time = microtime(true);
foreach ($url_arr as $url) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_exec($ch);
    curl_close($ch);
}
$end_time = microtime(true);
ob_end_clean();
echo 'Curl without handle reuse: ' . ($end_time - $start_time) . '<br>';

ob_start(); //Trying to avoid setting as many curl options as possible
$start_time = microtime(true);
$ch = curl_init();
foreach ($url_arr as $url) {
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_exec($ch);
}
curl_close($ch);
$end_time = microtime(true);
ob_end_clean();
echo 'Curl with handle reuse: ' . ($end_time - $start_time) . '<br>';

Et a obtenu le résultat suivant:

Curl sans réutilisation de la poignée: 3.7672290802002
Boucle avec réutilisation de la poignée: 3.0146431922913

Encore une augmentation de performance assez importante.

44
AlliterativeAlice

J'ai un scénario similaire où je publie des données sur un serveur. Il est divisé en requêtes de ~ 100 lignes, donc il produit beaucoup de requêtes. Dans une analyse comparative, j'ai comparé deux approches pour 12,614 lignes (127 demandes nécessaires) plus l'authentification et une autre demande de gestion interne (129 demandes au total).

Les requêtes passent par un réseau vers un serveur du même pays, pas sur site. Ils sont sécurisés par TLS 1.2 (la prise de contact aura également son prix, mais étant donné que HTTPS devient de plus en plus un choix par défaut, cela pourrait même le rendre plus similaire à votre scénario).

Avec la réutilisation cURL: un $curlHandle Qui est curl_init() 'édité une fois, puis modifié uniquement avec CURLOPT_URL Et CURLOPT_POSTFIELDS

Run  1: ~42.92s
Run  3: ~41.52s
Run  4: ~53.17s
Run  5: ~53.93s
Run  6: ~55.51s
Run 11: ~53.59s
Run 12: ~53.76s
Avg: 50,63s / Std.Dev: 5,8s
TCP-Conversations / SSL Handshakes: 5 (Wireshark)

Sans réutilisation cURL: un curl_init Par demande

Run  2: ~57.67s
Run  7: ~62.13s
Run  8: ~71.59s
Run  9: ~70.70s
Run 10: ~59.12s
Avg: 64,24s / Std. Dev: 6,5s
TCP-Conversations / SSL Handshakes: 129 (Wireshark)

Ce n'est pas le plus grand ensemble de données, mais on peut dire que toutes les exécutions "réutilisées" sont plus rapides que toutes les exécutions "init". Les temps moyens montrent une différence de près de 14 secondes.

7
amenthes

Cela dépend du nombre de demandes que vous ferez - les frais généraux pour la fermeture et la réouverture de chacun sont négligeables, mais quand vous en faites mille? Cela pourrait prendre quelques secondes ou plus.

Je pense que curl_multi_init serait la méthode la plus rapide.

Tout dépend du nombre de demandes que vous devez faire.

2
Adam Hopkinson

vérifiez cela aussi

 
 essayez {
 $ pool = new HttpRequestPool (
 new HttpRequest ($ q1), 
 new HttpRequest ($ qn) 
); 
 $ pool-> send (); 
 
 foreach ($ pool as $ request) {
 
 $ out [] = $ request-> getResponseBody (); 
 
} 
} catch (HttpException $ e) {
 echo $ e; 
} 
 
 
1
sathia