file_get_contents() с контекстом для использования http/1.1 со значительно более низкой скоростью загрузки

Использование кода ниже загрузки каждого изображения) file_get_contents() ) занимает в среднем 8-15 секунд.....

Если я не использую контекст для file_get_contents(), то загрузка изображения занимает меньше секунды.

Если я изменю $opts на ниже, я получу ту же производительность, что и file_get_contents() без контекста, который занимает около 13 секунд для обработки 2500 изображенийx.

$opts = array(
    'http'=>array(
        'protocol_version'=>'1.1',
        'method'=>'GET',
        'header'=>array(
            'Connection: close'
        ),
        'user_agent'=>'Image Resizer'
     )
); 

Воспроизвести:

    $start_time = mktime();
$products = array(
        array( 'code'=>'A123', 'image_url'=>'http://www.google.com/intl/en_ALL/images/srpr/logo1w.png' ),
        array( 'code'=>'A124', 'image_url'=>'http://www.google.com/intl/en_ALL/images/srpr/logo1w.png' ),
        array( 'code'=>'A125', 'image_url'=>'http://www.google.com/intl/en_ALL/images/srpr/logo1w.png' ),
        array( 'code'=>'A126', 'image_url'=>'http://www.google.com/intl/en_ALL/images/srpr/logo1w.png' ),
        array( 'code'=>'A127', 'image_url'=>'http://www.google.com/intl/en_ALL/images/srpr/logo1w.png' ),
        array( 'code'=>'A128', 'image_url'=>'http://www.google.com/intl/en_ALL/images/srpr/logo1w.png' ),
        array( 'code'=>'A134', 'image_url'=>'http://www.google.com/intl/en_ALL/images/srpr/logo1w.png' ),
        array( 'code'=>'A135', 'image_url'=>'http://www.google.com/intl/en_ALL/images/srpr/logo1w.png' ),
        array( 'code'=>'A146', 'image_url'=>'http://www.google.com/intl/en_ALL/images/srpr/logo1w.png' ),
        array( 'code'=>'A165', 'image_url'=>'http://www.google.com/intl/en_ALL/images/srpr/logo1w.png' )
    );

    if ( count( $products ) > 0 ) {
        $opts = array(
            'http'=>array(
                'protocol_version'=>'1.1',
                'method'=>'GET',
                'user_agent'=>'Image Resizer'
            )
        ); 
        $context = stream_context_create($opts);
        $def_width = 100;
        $max_width  = $def_width;
        foreach( $products as $product ) {
            $code = $product['code'];
            $folder = substr( $code, 0, 3 );
            echo( 'Looking at: ' .$product['code'] ."<br />" );
            $file = '/tmp/' .$folder .'/' .$code .'_' .$def_width .'.jpg';
            $filemtime = @filemtime($file);
            $gen_file = true;
            if ( $filemtime !== false ) {
                $file_age = (time() - $filemtime);
                if ( $file_age <= 300 ) {
                    $gen_file = false;
                }
            }
            echo( '&nbsp;&nbsp;&nbsp;&nbsp;File not cached or cached file has expired<br />' );
            if ( $gen_file ) {
                echo( '&nbsp;&nbsp;&nbsp;&nbsp;Getting File...');
                $imgStr = file_get_contents( $product['image_url'], false, $context );
                $img = @imagecreatefromstring($imgStr);
                if ( is_resource( $img ) ) {
                    echo( 'DONE' .'<br />' );
                    $image_x = imagesx($img);
                    $image_y = imagesy($img);
                    if ( $def_width >= $image_x ) {
                        $def_width = $image_x;
                    }
                    echo( '&nbsp;&nbsp;&nbsp;&nbsp;Calculating Scale<br />' );
                    $ts = min( $max_width/$image_x,$max_width/$image_y);
                    $thumbhght = $ts * $image_y;
                    $thumbwth = $ts * $image_x;

                    $thumb_image_resized = imagecreatetruecolor( $thumbwth, $thumbhght);
                    imagecopyresampled($thumb_image_resized, $img, 0, 0, 0, 0, $thumbwth, $thumbhght, $image_x, $image_y );
                    echo( '&nbsp;&nbsp;&nbsp;&nbsp;Checking For Directory<br />' );
                    if ( !is_dir( '/tmp/' .$folder ) ) {
                        mkdir( '/tmp/' .$folder );
                    }
                    echo( '&nbsp;&nbsp;&nbsp;&nbsp;Writing File<br />' );
                    $new_file = '/tmp/' .$folder .'/' .$code .'_' .$def_width .'.jpg';

                    imagejpeg( $thumb_image_resized, $new_file, 100);
                    echo( '&nbsp;&nbsp;&nbsp;&nbsp;DONE<br />' );

                    imagedestroy($img);
                    imagedestroy($thumb_image_resized);
                } else {
                    echo( 'Problem Getting Image<br />' );
                    die();
                }
            } else {
                echo( '&nbsp;&nbsp;&nbsp;&nbsp;Already Exists<br />' );
            }
        }
    }
    $end_time = mktime();
    echo( 'Completed In...' .($end_time - $start_time ) .' seconds(s)<br />' );

person dorgan    schedule 15.08.2010    source источник


Ответы (2)


Запросы HTTP 1.1 конвейеризируются по умолчанию. Если вы не «Соединение: Закрыть», предполагается «Соединение: Keep-Alive», а затем вам нужно дождаться истечения времени ожидания соединения (поскольку вы никогда не закрывали его явно), прежде чем начнется следующий цикл.

person TML    schedule 15.08.2010
comment
Благодарю вас! Запросы, которые выполнялись за 0,15 с в HTTP 1.0, выполнялись не менее 5 с в HTTP 1.1. Простой `заголовок (Соединение: закрыть); починил это! - person Mave; 25.03.2015

Ваш контекст говорит file_get_contents() каждый раз закрывать HTTP-соединение. Возможно, поэтому код работает так долго, так как много раз закрывает и снова открывает соединения? Я не знаком с внутренним устройством file_get_contents(), но вы можете настроить контекст, чтобы использовать «Соединение: поддерживать активность» для всех соединений, кроме последнего, и «Соединение: закрыть» для последнего.

person Kai Chan    schedule 15.08.2010
comment
Я бы ожидал, что file_get_contents() закроет свое соединение в любом случае - он закрывает дескрипторы файлов при чтении файлов с диска. Если вам нужна производительность, лучше выбрать cURL. Вы можете просто повторно использовать один и тот же дескриптор curl снова и снова; соединение остается открытым по умолчанию, если я правильно помню. - person Frank Farmer; 15.08.2010
comment
Я согласен с вами по поводу использования cURL, если только нет причин, по которым dorgan должен использовать file_get_contents(). - person Kai Chan; 15.08.2010