PHP – Различия между `get_headers` и` stream_get_meta_data`?

Вступление / отказ от ответственности

Достойные куски – это результаты, которые в значительной степени можно игнорировать. Это все еще немного читатель, но я стараюсь быть основательным в своем анализе и опросе. Если вы знакомы с stream_get_meta_data , вам было бы stream_get_meta_data перейти к «Вопросам» в конце .

Кроме того, что в DOC, у меня возникли проблемы с поиском stream_get_meta_data в stream_get_meta_data PHP. Общая функциональность не сильно отличается от функциональности PHP get_headers , но я не могу на всю жизнь найти какие-либо сравнения между ними, или плюсы / минусы get_headers .

Настройка

До этого момента я всегда использовал PHP get_headers для проверки правильности URL. Недостатком get_headers является то, что он, как известно, медленный . Понятно, что большая часть задержек связана напрямую с сервером, на котором размещается интересующий сайт, но, возможно, метод слишком чрезмерен, или что-то еще замедляет его.

Существует множество ссылок, которые рекомендуют использовать CURL , утверждая, что это быстрее, но я запускаю бок о бок, время тестов обоих, и get_headers всегда выходит на первое место, часто в 1,5 или 2 раза.

Я еще не видел никаких решений, использующих stream_get_meta_data , и только недавно наткнулся на него впервые. Я исчерпал свои навыки Google, без большой удачи. Но, в интересах оптимизации моей схемы, я провел несколько тестов.

Тестирование

Сравнение между get_headers и stream_get_meta_data выполнялось с использованием списка из 106 текущих (т.е. живых, действительных, статусных = 200) URL-адресов:

Code Block #1

 // All URLs in format "http://www.domain.com" $urls = array('...', '...', '...'); // *106 URLs // get_headers $start = microtime(true); foreach($urls as $url) { try{ // Unfortunately, get_headers does not offer a context argument stream_context_set_default(array('http' => array('method' => "HEAD"))); $headers[] = @get_headers($url, 1); stream_context_set_default(array('http' => array('method' => "GET"))); }catch(Exception $e){ continue; } } $end1 = microtime(true) - $start; // stream_get_meta_data $cont = stream_context_create(array('http' => array('method' => "HEAD"))); $start = microtime(true); foreach($urls as $url) { try{ $fp = fopen($url, 'rb', false, $cont); if(!$fp) { continue; } $streams[] = stream_get_meta_data($fp); }catch(Exception $e){ continue; } } $end2 = microtime(true) - $start; 

И результаты, которые я получаю, – это stream_get_meta_data выходящие сверху, 90% времени или больше . Иногда времена почти идентичны, но чаще всего stream_get_meta_data имеет более короткое время выполнения

Run Times #1

 "get_headers": 112.23 // seconds "stream_get": 42.61 // seconds 

С [строгими] выводами этих двух будет что-то вроде:

Excerpt of Comparison #1

 url .. "http://www.wired.com/" get_headers | 0 ............................ "HTTP/1.1 200 OK" | Access-Control-Allow-Origin .. "*" | Cache-Control ................ "stale-while-revalidate=86400, stale-while-error=86400" | Content-Type ................. "text/html; charset=UTF-8" | Link ......................... "; rel=\"https://api.w.org/\"" | Server ....................... "Apache" | Via | | "1.1 varnish" | | "1.1 varnish" | | Fastly-Debug-State ........... "HIT" | Fastly-Debug-Digest .......... "c245efbf14778c681ce317da114c1a762199e1326323d07b531d765e97fc8695" | Content-Length ............... "135495" | Accept-Ranges ................ "bytes" | Date ......................... "Tue, 23 Aug 2016 22:32:26 GMT" | Age .......................... "701" | Connection ................... "close" | X-Served-By .................. "cache-jfk8149-JFK, cache-den6024-DEN" | X-Cache ...................... "HIT, HIT" | X-Cache-Hits ................. "51, 1" | X-Timer ...................... "S1471991546.459931,VS0,VE0" | Vary ......................... "Accept-Encoding" stream_get | wrapper_data | | "HTTP/1.1 200 OK" | | "Access-Control-Allow-Origin: *" | | "Cache-Control: stale-while-revalidate=86400, stale-while-error=86400" | | "Content-Type: text/html; charset=UTF-8" | | "Link: ; rel=\"https://api.w.org/\"" | | "Server: Apache" | | "Via: 1.1 varnish" | | "Fastly-Debug-State: HIT" | | "Fastly-Debug-Digest: c245efbf14778c681ce317da114c1a762199e1326323d07b531d765e97fc8695" | | "Content-Length: 135495" | | "Accept-Ranges: bytes" | | "Date: Tue, 23 Aug 2016 22:32:26 GMT" | | "Via: 1.1 varnish" | | "Age: 701" | | "Connection: close" | | "X-Served-By: cache-jfk8149-JFK, cache-den6020-DEN" | | "X-Cache: HIT, HIT" | | "X-Cache-Hits: 51, 1" | | "X-Timer: S1471991546.614958,VS0,VE0" | | "Vary: Accept-Encoding" | | wrapper_type ................. "http" | stream_type .................. "tcp_socket/ssl" | mode ......................... "rb" | unread_bytes ................. 0 | seekable ..................... false | uri .......................... "http://www.wired.com/" | timed_out .................... false | blocked ...................... true | eof .......................... false 

По большей части все те же данные, за исключением того, что stream_get_meta_data не предлагает никакого способа включить ключи для wrapper_data , без разбора вручную.

Легко …

Code Block #2.1/2.2

 $wd = $meta[$url]['wrapper_data']; $wArr = wrapperToKeys($wd); 

где…

 function wrapperToKeys($wd) { $wArr = array(); foreach($wd as $row) { $pos = strpos($row, ': '); // *Assuming* that all separated by ": " (Might be colon, without the space?) if($pos === false) { $wArr[] = $row; }else { // $pos, $key and $value can probably be done with one good preg_match $key = substr($row, 0, $pos); $value = substr($row, ($pos + 2)); // If key doesn't exist, assign value if(empty($wArr[$key])) { $wArr[$key] = $value; } // If key already points to an array, add value to array else if(is_array($wArr[$key])) { $wArr[$key][] = $value; } // If key currently points to string, swap value into an array else { $wArr[$key] = array($wArr[$key], $value); } } } return $wArr; } 

И результат идентичен get_headers($url, 1) :

Excerpt of Comparison #2

 url .. "http://www.wired.com/" headers | 0 ............................ "HTTP/1.1 200 OK" | Access-Control-Allow-Origin .. "*" | Cache-Control ................ "stale-while-revalidate=86400, stale-while-error=86400" | Content-Type ................. "text/html; charset=UTF-8" | Link ......................... "; rel=\"https://api.w.org/\"" | Server ....................... "Apache" | Via | | "1.1 varnish" | | "1.1 varnish" | | Fastly-Debug-State ........... "HIT" | Fastly-Debug-Digest .......... "c245efbf14778c681ce317da114c1a762199e1326323d07b531d765e97fc8695" | Content-Length ............... "135495" | Accept-Ranges ................ "bytes" | Date ......................... "Tue, 23 Aug 2016 22:35:29 GMT" | Age .......................... "883" | Connection ................... "close" | X-Served-By .................. "cache-jfk8149-JFK, cache-den6027-DEN" | X-Cache ...................... "HIT, HIT" | X-Cache-Hits ................. "51, 1" | X-Timer ...................... "S1471991729.021214,VS0,VE0" | Vary ......................... "Accept-Encoding" w-arr | 0 ............................ "HTTP/1.1 200 OK" | Access-Control-Allow-Origin .. "*" | Cache-Control ................ "stale-while-revalidate=86400, stale-while-error=86400" | Content-Type ................. "text/html; charset=UTF-8" | Link ......................... "; rel=\"https://api.w.org/\"" | Server ....................... "Apache" | Via | | "1.1 varnish" | | "1.1 varnish" | | Fastly-Debug-State ........... "HIT" | Fastly-Debug-Digest .......... "c245efbf14778c681ce317da114c1a762199e1326323d07b531d765e97fc8695" | Content-Length ............... "135495" | Accept-Ranges ................ "bytes" | Date ......................... "Tue, 23 Aug 2016 22:35:29 GMT" | Age .......................... "884" | Connection ................... "close" | X-Served-By .................. "cache-jfk8149-JFK, cache-den6021-DEN" | X-Cache ...................... "HIT, HIT" | X-Cache-Hits ................. "51, 1" | X-Timer ...................... "S1471991729.173641,VS0,VE0" | Vary ......................... "Accept-Encoding" 

Даже при сортировке ключей stream_get_meta_data является чемпионом:

Sample Run Times #2

 "get_headers": 99.51 // seconds "stream_get": 43.79 // seconds 

Примечание. Эти тесты запускаются на дешевом общем сервере – следовательно, большие вариации времени тестирования. При этом разрыв между этими двумя методами очень согласован между испытаниями.

дополнительный

Для тех из вас, кто понимает c-код для PHP и чувствую, что они могут получить некоторое представление о нем, определения функций можно найти по адресу:

'get_headers' (PHP Git)

а также

'stream_get_meta_data' (PHP Git)

Вопросов

  1. Почему stream_get_meta_data настолько недопредставлена ​​(в поисках и доступных фрагментах кода) по сравнению с get_headers ?

    То, как я это сформулировал, приводит к мнению , но мои намерения более stream_get_meta_data на следующие: «Есть ли что-то настолько известное и ужасное в stream_get_meta_data которое препятствует людям использовать его?»

  2. Как и в предыдущем, есть ли хорошо известные отраслевые плюсы и минусы между этими двумя? Виды вещей, на которые ссылается более полное понимание CS. Возможно, get_headers является более безопасным / надежным и менее восприимчивым к ne'erdowells и несогласованностью с выводами сервера? Или, может быть, get_headers как известно, работает в тех экземплярах, где stream_get_meta_data и ошибки?

    Из того, что я могу найти, у stream_get_meta_data есть пара заметок и предупреждений (… для fopen) , но ничего ужасного, что их нельзя обойти.

До тех пор, пока это безопасно и непротиворечиво, я хотел бы включить его в свой проект, поскольку эта операция выполняется часто , и сокращение времени выполнения пополам будет иметь существенное значение.

Редактировать # 1

С тех пор я нашел несколько URL-адресов, которые успешно работают с get_headers но get_headers предупреждение для stream_get_meta_data

 PHP Warning: fopen(http://www.alealimay.com/): failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request PHP Warning: fopen(http://www.thelovelist.net/): failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request PHP Warning: fopen(http://www.bleedingcool.com/): failed to open stream: HTTP request failed! HTTP/1.1 403 Forbidden 

get_headers возвращает только статус 403 Forbidden , даже если вы можете вставлять URL-адреса в браузер и видеть, что они являются рабочими сайтами.

Непонятно об этом: и stream_get_meta_data , и неполный заголовок из get_headers (должны включать в себя все переадресации и final status_code = 200 для действующих сайтов).


Большое спасибо, если вы сделали это так далеко.

Кроме того, прокомментируйте, если вы проголосуете, так что я могу усовершенствовать этот вопрос, и мы все можем узнать о будущих делах.

Solutions Collecting From Web of "PHP – Различия между `get_headers` и` stream_get_meta_data`?"