Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Для профи > CURL расходует много памяти!


Автор: kanaris 29.10.2010, 22:13
Всем привет!

Создал многопоточный скрипт прокси-чекер (за счет функций curl_multi_*).
Проверяет прокси, одновременно в 10-20 потоков.
Как только ответ от прокси получен, дескриптор удаляется, на его место ставится следующее прокси.

Поставил работать скрипт, работает довольно быстро. Но где-то на 950-м прокси компьютер затормозил. В диспетчере задач файл подкачки использован почти под завязку!
Трассировал хДебагом, он показывает изменения памяти максимум мегабайт на 5. Но фактически файл подкачки увеличивается в объеме мегабайт на 500-1000!

Вот скрин диспетчера:
user posted image

Сам скрипт:

Код

$test_url='http://example.com/';
$max_threads=20;

$proxylist=file_get_contents('http_proxy.txt');

$sep=explode("\n",$proxylist);
$proxylist=array();
foreach($sep as $v){
    $r=explode(':',$v);
    $proxylist[]=array(
        'host'=>$r[0],
        'port'=>$r[1]
    );
}

$chs = array();
foreach($proxylist as $v){
    $ch=curl_init();
    curl_setopt_array($ch,array(
        CURLOPT_URL=>$test_url,
        CURLOPT_HEADER=>true,
        CURLOPT_RETURNTRANSFER=>true,
        CURLOPT_FAILONERROR=>false,
        CURLOPT_PROXY=>$v['host'],
        CURLOPT_PROXYPORT=>$v['port'],
        CURLOPT_CONNECTTIMEOUT=>10,
        CURLOPT_TIMEOUT=>20,
    ));
    $chs[]=$ch;
}

$result=array();
$active_threads=array();
$active=0;
$queue_pointer=0;
$mh=curl_multi_init();

do{// выполняется, пока все не будет выполнено
    if($active<$max_threads && $queue_pointer<count($chs)){// добавить в очередь
        curl_multi_add_handle($mh,$chs[$queue_pointer]);
        $queue_pointer++;
    }
    $mrc=curl_multi_exec($mh,$active);
    //$active_threads[]=$active;
    $r=curl_multi_info_read($mh);
    if(is_array($r)){// если готов какой-нибудь контент, записать
        $content=curl_multi_getcontent($r['handle']);
        $info=curl_getinfo($r['handle']);
        //foreach($chs as $k=>$curldsc)if($curldsc==$r['handle']){curl_close($chs[$k]);unset($chs[$k]);} // ---- не помогает
        curl_multi_remove_handle($mh,$r['handle']);
        curl_close($r['handle']);

        $result[]=array(
            'content'=>$content,
            'info'=>$info,
            'code'=>$r['result'],
        );

        /*unset($r['handle']);  ---- тоже не помогает
        unset($content);
        unset($info);
        unset($r);*/
        
    }
}while(($mrc==CURLM_CALL_MULTI_PERFORM || $active) && file_get_contents('stop.txt')=='');

curl_multi_close($mh);




Как решить проблему?

Автор: masp 29.10.2010, 23:21
попробуй на UNIXе   запустить,
а также читал где то unset реально не осовбождает память,
http://www.rsdn.ru/forum/web/2194680.flat.aspx
и вот ещё
http://rmcreative.ru/blog/post/utechki-pamjati-v-php

Автор: Pfailed 28.11.2010, 22:06
Может быть не складывать в массив?
Код

$result[]=array(
            'content'=>$content,
            'info'=>$info,
            'code'=>$r['result'],
        );


Не удивительно, что это может сожрать память.

Автор: kanaris 6.12.2010, 18:50
Цитата

Не удивительно, что это может сожрать память.


даже если я закоментирую это, всеравно жрет.

Автор: topy 6.12.2010, 22:28
Как вам уже написали, попробуйте на Unix`е запустить.
Говорят, что curl.exe некорректно работает.

Автор: vfz4z 22.12.2011, 15:43
дайте мне список прокси и я сам запущу этот скрипт... Очень походе что память не освобождает curl. У меня под рукой так-же несколько win серверов, так что интересно будет протестить всё это дело и сравнить результаты... Хотя вопрос наверное уже мёртв)

Автор: MuToGeN 10.1.2012, 02:37
Хехе, знакомая задача. Когда-то делал аналогичное для одного проекта. Посетителей надо было пробивать на то, с прокся они заходят или нет.
Из собственного опыта:
1. Нормальной многопоточности в PHP нет и никогда не было, даже в CLI SAPI. Да, про pcntl знаю.
2. Если только PHP, то организовывать лучше как "мастер-слейв". Мастер запускает дочерний процесс, который принимает задачу с командной строки, куда-то отписывается о результате и успешно завершает исполнение. В этом случае ОС следит за всеми возможными косяками по утечкам памяти.
3. Если это под серьёзные промышленные нагрузки, то лучше старый-добрый C, тот же curl и pthreads. Потому что задача по большому счету не для похапе.
3.1 Если это под действительно серьезные промышленные нагрузки, то забудьте про windows.

Добавлено через 44 секунды
Чорт smile я буду смотреть на дату поста, я буду смотреть на дату поста, я буду смотреть на дату поста, я буду смотреть на дату поста -)

Автор: kanaris 22.8.2012, 22:28
Цитата
Хотя вопрос наверное уже мёртв) 

Цитата

Добавлено через 44 секунды
Чорт  я буду смотреть на дату поста, я буду смотреть на дату поста, я буду смотреть на дату поста, я буду смотреть на дату поста -) 


Да чо, я иногда почитываю свои старые темы, а вдруг ответили что нибудь толкового =)
Просто как правило, вопросы не решаются, поэтому идея забрасывается в дальний угол, до поры до времени. Вопросы всегда актуальны для меня...


Цитата

дайте мне список прокси и я сам запущу этот скрипт...

Прокси обычные паблик, например http://samair.ru/proxy/

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)