{"id":1792,"date":"2014-08-29T05:26:02","date_gmt":"2014-08-29T03:26:02","guid":{"rendered":"http:\/\/blog.nebule.org\/?p=1792"},"modified":"2016-03-29T19:00:46","modified_gmt":"2016-03-29T17:00:46","slug":"io-http-et-performances-dans-php","status":"publish","type":"post","link":"http:\/\/blog.nebule.org\/?p=1792","title":{"rendered":"IO HTTP et performances dans PHP"},"content":{"rendered":"<p style=\"text-align: justify;\">Pour les besoins du module des IO sur <em>HTTP<\/em>, j&rsquo;ai r\u00e9alis\u00e9 quelques tests afin de d\u00e9terminer la meilleur m\u00e9thode pour v\u00e9rifier la pr\u00e9sence d&rsquo;un dossier ou d&rsquo;un fichier sur un serveur web via <em>HTTP<\/em>.<\/p>\n<p style=\"text-align: justify;\">La m\u00e9thode la plus simple consiste \u00e0 appeler l&rsquo;URL de ce que l&rsquo;on veut avec l&rsquo;instruction <code>file_get_contents<\/code>.<br \/>\nC&rsquo;est tr\u00e8s simple mais tr\u00e8s lent puisque tout le contenu est t\u00e9l\u00e9charg\u00e9 alors que l&rsquo;on ne souhaite que l&rsquo;ent\u00eate de la r\u00e9ponse du serveur. En fait, on a juste besoin de la premi\u00e8re ligne de la r\u00e9ponse pour conna\u00eetre le code de r\u00e9ponse du serveur, 200 si un fichier est disponible. 404 si le fichier n&rsquo;existe pas. 403 si le fichier n&rsquo;est pas accessible pour cause de restriction.<br \/>\nA noter que cette instruction et d&rsquo;autres comme <code>fopen<\/code> n\u00e9cessitent d&rsquo;autoriser explicitement l&rsquo;ouverture des URL avec <code>allow_url_fopen=On<\/code> et <code>allow_url_include=On<\/code>. Ces options sont n\u00e9cessaires au bon fonctionnement du bootstrap, cela n&rsquo;introduit donc pas de configuration suppl\u00e9mentaire.<\/p>\n<p style=\"text-align: justify;\">La seconde m\u00e9thode consiste \u00e0 demander l&rsquo;ent\u00eate (<em>header<\/em>) via l&rsquo;instruction <em>PHP<\/em> correspondante,\u00c2\u00a0<code>get_headers<\/code>.<br \/>\nSauf que ce n&rsquo;est pas mieux puisque le contenu est malgr\u00e9 tout t\u00e9l\u00e9charg\u00e9 m\u00eame si au final on n&rsquo;extrait que l&rsquo;ent\u00eate.<\/p>\n<p style=\"text-align: justify;\">Une autre m\u00e9thode consiste \u00e0 utiliser la librairie <em>CURL<\/em> dans <em>PHP<\/em>. Cette librairie est sp\u00e9cialis\u00e9e dans les manipulations des URL, mais cela oblige \u00e0 l&rsquo;installer, ce qui n&rsquo;est pas forc\u00e9ment la meilleur solution.<br \/>\nPar contre, en terme de performance, c&rsquo;est d&rsquo;un autre niveau. On peut raisonnablement savoir si un gros fichier est pr\u00e9sent sur le serveur sans avoir de temps de latence d\u00e9mesur\u00e9. Au moins pour ces performances, cela peut valoir le co\u00fct d&rsquo;installer cette librairie.<\/p>\n<p style=\"text-align: justify;\">Enfin, une derni\u00e8re solution consiste \u00e0 g\u00e9n\u00e9rer soit-m\u00eame la requ\u00eate \u00e0 transmettre au serveur et d&rsquo;analyse la r\u00e9ponse. Cela peut \u00eatre fait avec l&rsquo;instruction <code>fsockopen<\/code>. Mais il faut tout faire, g\u00e9n\u00e9rer la requ\u00eate, la transmettre, recevoir la r\u00e9ponse et la traiter.<br \/>\nLa requ\u00eate doit \u00eatre du type <strong>HEAD<\/strong> pour n&rsquo;avoir que l&rsquo;ent\u00eate.<br \/>\nApr\u00e8s avoir fait divers tests, cette derni\u00e8re solution semble la plus rapide.<\/p>\n<p style=\"text-align: justify;\">Voir les temps de r\u00e9ponses pour savoir si le dossier <code>l<\/code> est pr\u00e9sent sur le serveur web local (CF code en annexe) :<\/p>\n<pre style=\"text-align: justify;\"> file_get_contents\n HTTP\/1.1 200 OK\n 2.0584919452667s\n\n get_headers\n HTTP\/1.1 200 OK\n 1.8262121677399s\n\n curl\n 200\n 0.006443977355957s\n\n fsockopen\n 200\n 0.0010509490966797s<\/pre>\n<p style=\"text-align: justify;\">Le dossier en question contient 24000 fichiers.<br \/>\nIl est clair de <code>fsockopen<\/code> est la solution la plus performante. C&rsquo;est celle qui sera utilis\u00e9e.<\/p>\n<p style=\"text-align: justify;\">Je ne traite pas le cas des renvois type 301 puisqu&rsquo;il n&rsquo;est pas pr\u00e9vu pour l&rsquo;instant dans la librairie <em>nebule<\/em> de suivre ces renvois.<\/p>\n<p style=\"text-align: justify;\"><!--more--><\/p>\n<p style=\"text-align: justify;\"><strong>Annexe<\/strong> :<\/p>\n<p style=\"text-align: justify;\">Code des tests :<\/p>\n<pre style=\"text-align: justify;\">&lt;?php\n$url = \"http:\/\/localhost\/l\/\";\n\necho \"file_get_contents&lt;br \/&gt;n\";\n$start_time = microtime(TRUE);\n$response = file_get_contents($url);\necho $http_response_header[0].\"&lt;br&gt;n\";\n$end_time = microtime(TRUE);\necho $end_time - $start_time.\"s&lt;br&gt;n&lt;br \/&gt;n\";\n\necho \"get_headers&lt;br \/&gt;n\";\n$start_time = microtime(TRUE);\n$headers = get_headers($url);\necho $headers[0].\"&lt;br&gt;n\";\n$end_time = microtime(TRUE);\necho $end_time - $start_time.\"s&lt;br&gt;n&lt;br \/&gt;n\";\n\necho \"curl&lt;br \/&gt;n\";\n$start_time = microtime(TRUE);\n$handle = curl_init($url);\ncurl_setopt($handle,\u00c2\u00a0 CURLOPT_RETURNTRANSFER, TRUE);\ncurl_setopt($handle, CURLOPT_NOBODY, 1); \/\/ and *only* get the header \n\/* Get the HTML or whatever is linked in $url. *\/\n$response = curl_exec($handle);\n\/* Check for 404 (file not found). *\/\n$httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);\n\/\/ if($httpCode == 404) {\n\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 \/\/ \/* Handle 404 here. *\/\n\/\/ }\necho $httpCode.\"&lt;br&gt;n\";\ncurl_close($handle);\n$end_time = microtime(TRUE);\necho $end_time - $start_time.\"s&lt;br&gt;n&lt;br \/&gt;n\";\n\necho \"fsockopen&lt;br \/&gt;n\";\n$start_time = microtime(TRUE);\n$purl=parse_url($url);\n$fp = fsockopen($purl['host'], 80, $errno, $errstr, 1);\nif ($fp !== false)\n{\n\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 $out\u00c2\u00a0 = \"HEAD \".$purl['path'].\" HTTP\/1.1rn\";\n\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 $out .= \"Host: \".$purl['host'].\"rn\";\n\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 $out .= \"Connection: Closernrn\";\n\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 $response = '';\n\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 fwrite($fp, $out);\n\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 while (!feof($fp))\n\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 {\n\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 $response .= fgets($fp,20);\n\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 if ( sizeof($response) &gt; 0 ) break;\n\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 }\n}\n$code = substr($response, strpos($response, ' ') + 1, 3);\necho $code.\"&lt;br&gt;n\";\n$end_time = microtime(TRUE);\necho $end_time - $start_time.\"s&lt;br&gt;n&lt;br \/&gt;n\";<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Pour les besoins du module des IO sur HTTP, j&rsquo;ai r\u00e9alis\u00e9 quelques tests afin de d\u00e9terminer la meilleur m\u00e9thode pour v\u00e9rifier la pr\u00e9sence d&rsquo;un dossier ou d&rsquo;un fichier sur un serveur web via HTTP. La m\u00e9thode la plus simple consiste \u00e0 appeler l&rsquo;URL de ce que l&rsquo;on veut avec l&rsquo;instruction file_get_contents. C&rsquo;est tr\u00e8s simple mais &hellip; <a href=\"http:\/\/blog.nebule.org\/?p=1792\" class=\"more-link\">Continuer la lecture de <span class=\"screen-reader-text\">IO HTTP et performances dans PHP<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[92,7,13,16,20],"tags":[],"_links":{"self":[{"href":"http:\/\/blog.nebule.org\/index.php?rest_route=\/wp\/v2\/posts\/1792"}],"collection":[{"href":"http:\/\/blog.nebule.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.nebule.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.nebule.org\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.nebule.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1792"}],"version-history":[{"count":1,"href":"http:\/\/blog.nebule.org\/index.php?rest_route=\/wp\/v2\/posts\/1792\/revisions"}],"predecessor-version":[{"id":2167,"href":"http:\/\/blog.nebule.org\/index.php?rest_route=\/wp\/v2\/posts\/1792\/revisions\/2167"}],"wp:attachment":[{"href":"http:\/\/blog.nebule.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1792"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.nebule.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1792"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.nebule.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1792"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}