Модераторы: korob2001, ginnie

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Сравнение многопоточности и Async, Parallel, Кто нибудь реально пробовал??? 
:(
    Опции темы
burakov
Дата 12.5.2011, 11:31 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 554
Регистрация: 28.7.2006

Репутация: нет
Всего: нет




Написал грабер на основе
HTTP-Async-0.09.tar.gz
вот инфу нашел отсюда http://www.snippy.ru/snippet/1708-perl-asi...-http-klientov/

И вообщем сравниваю свой многопоточный на threads Сделанный и новый на async: многопоточный реально работает быстрее -  хотя количество потоков ставлю 20 - как по умолчанию параметр slots у этого async... По идее должно быть одинаково...

Кто нибудь делал граберы на async, LWP::Parallel и т.п. сравнивал их производительность с реальным многопоточным решением??? Почему разница в скорости?







--------------------
Нотный архив http://libnote.ru скачать ноты бесплатно
PM MAIL   Вверх
Pfailed
Дата 12.5.2011, 11:49 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 19.7.2009

Репутация: 2
Всего: 39



Когда речь идёт о вводе/выводе использование потоков просто избыточно, особенно таких тяжёлых, как в perl.
Единственно для чего тут соит применить потоки это разбить процесс на кол-во потоков равных количеству процессоров, а в каждом уже использовать неблокирующий ввод/вывод. Такой вариант будет быстрее создания отдельного потока для каждого соединения. Плюс потребует гораздо меньше памяти.
Составляйте минимальный пример обоих варинатов и показывайте. Там уже можно будет сказать почему первое быстрее второго или наоборот.



--------------------
PM MAIL   Вверх
DurRandir
Дата 12.5.2011, 13:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 335
Регистрация: 27.9.2009

Репутация: 1
Всего: 17



Код

sleep $self->poll_interval;


Ололо! Модуль жжот) 

Это сообщение отредактировал(а) DurRandir - 12.5.2011, 13:21
PM   Вверх
Pfailed
Дата 12.5.2011, 13:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 19.7.2009

Репутация: 2
Всего: 39



Цитата(DurRandir @ 12.5.2011,  13:21)
Код

sleep $self->poll_interval;


Ололо! Модуль жжот)

Учитывая, что по дефолту poll_interval = 0.05, а sleep принимает только целочисленные аргументы, эта конструкция эквивалентна sleep(0), т.е. пустой конструкции.
Другая более очевидная проблема этого модуля - синхронные запросы dns. А один из таких запросов в худшем случае может заблокировать всю программу на минуты. Один из модулей где решена эта проблема носит название AnyEvent::HTTP.



--------------------
PM MAIL   Вверх
burakov
Дата 12.5.2011, 14:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 554
Регистрация: 28.7.2006

Репутация: нет
Всего: нет



Ну не знаю, грабер на потоках работает так как ему и положено.

И так быстро как захочешь - поставил 2 потока - медленнее, поставил 20 - быстрее.
Нареканий к нему нет. Хоть и потоки много памяти занимают и т.д. - главное работает как и задумывалось, 

а вот грабер на async ведет себя непонятно - ставишь 
ему slots = 20 - он вообще замирает, ставишь slots = 2 - вроде как работает быстрее, то есть ведет себя прямо противоположно ожидаемому.

алгоритм грабера таков:

1. $async -> add (Стартовый URL)
 
while ( my $res = $async -> wait_for_next_response) {  
    1. Сохраняю контент и ищу новые ссылки - пишу их в БД
    2. Выбираю из БД ссылки и добавляю и делаю $async -> add (url)
}


Все вроде бы понятно - просто работает такая схема непонятно...

poll_interval
 Задержка - 0,05 секунды - маленькая. ее можно в расчет не брать. Грабер виснет - на гораздо более продолжительное время...


Синхронные запросы ДНС- в многопоточном грабере - тоже ведь ДНС синхронно запрашивается ???? однако все работает быстро и ничего не вешается на минуты и более...

Сейчас, конечно посмотрю HTTP::Event, но все же...


--------------------
Нотный архив http://libnote.ru скачать ноты бесплатно
PM MAIL   Вверх
Pfailed
Дата 12.5.2011, 14:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 19.7.2009

Репутация: 2
Всего: 39



Еще немного посмотрел в HTTP::Async. Его вторая беда - блокирующийся connect.
Простой скрипт выводящий из строя всю Async'хронность
Код

use HTTP::Async;
use HTTP::Request;
use strict;

my $async = HTTP::Async->new;
warn 'before first add: ', time();
$async->add(HTTP::Request->new(GET => 'http://perlmonks.org'));
warn 'after first add: ', time();

warn 'before second add: ', time();
$async->add(HTTP::Request->new(GET => 'http://waitpid.org'));
warn 'after second add: ', time();

warn 'before third add: ', time();
$async->add(HTTP::Request->new(GET => 'http://google.ru'));
warn 'after third add: ', time();



Сервер добавляемый вторым в данный момент выключен. В итоге весь скрипт зависает на неопределенное время.
Итого: HTTP::Async для реальных задач использовать я не рекомендую.



--------------------
PM MAIL   Вверх
burakov
Дата 12.5.2011, 15:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 554
Регистрация: 28.7.2006

Репутация: нет
Всего: нет



А что порекомендуете использовать для реальных задач?
Чтобы было уже проверено? и можно было отказаться от threads... (иногда таки дает ошибку памяти под WIN32, да и код посложнее)

ParallelUserAgent-2.57.tar.gz?


--------------------
Нотный архив http://libnote.ru скачать ноты бесплатно
PM MAIL   Вверх
DurRandir
Дата 12.5.2011, 16:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 335
Регистрация: 27.9.2009

Репутация: 1
Всего: 17



>Pfailed
Там есть импорт правильного слипа из Time::HiRes

>burakov
Был же уже назван модуль - AnyEvent::HTTP. Есть альтернативные подходы - к примеру, IO::Lambda.
PM   Вверх
Pfailed
Дата 12.5.2011, 18:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 19.7.2009

Репутация: 2
Всего: 39



Цитата(DurRandir @  12.5.2011,  16:00 Найти цитируемый пост)
Там есть импорт правильного слипа из Time::HiRes

Ага точно, значит еще 1 минус в карму этому модулю  smile 


--------------------
PM MAIL   Вверх
EcSYZ
Дата 12.5.2011, 21:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 79
Регистрация: 21.6.2007

Репутация: нет
Всего: 1



threads можно юзать там, где нет сложных структур данны, т.е. где можно не слишком загонятся с синхронизацией.
В то время как Anyevent::HTTP позволяет вообще не задумываться не о какой синхронизации и работать почти как с однопоточным скриптом.
Вот только если с threads ещё можно написать чтото через жопу и оно будет работать(возможно даже без глюков), то от anyevent быстро остановится, так как для этого достаточно если один коллбэк загнётся.
У меня есть скрипт на Anyevent::HTTP и через него прошло уже как минимум 60к линков и без каких либо проблем.
PM MAIL WWW   Вверх
EcSYZ
Дата 12.5.2011, 22:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 79
Регистрация: 21.6.2007

Репутация: нет
Всего: 1



На счёт сравнение скорости:
Так как Anyevent(и все другие событийные машины) не чистая многопоточность, то в случае если один коллбэк задержится, то следующая пачка запросов будет ждать этот 1 коллбэк.
Это конечно не особо приятно, но если вы пишите не паука для гугла который должен обходить милионы сайтов супер-пупер-мего быстро, то с этими небольшими потерями можно смирится.
PM MAIL WWW   Вверх
burakov
Дата 13.5.2011, 09:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 554
Регистрация: 28.7.2006

Репутация: нет
Всего: нет



Ну не знаю, 
на Anyevent::HTTP у меня ума не хватило, зато я адаптировал 
под себя ParallelUserAgent-2.57.tar.gz

Код

use strict;
use warnings;

$SIG{PIPE} = 'IGNORE';  
use LWP::Parallel::UserAgent;  

my @urls    = (  
  'http://libnote.ru',  
);  
my $ua = LWP::Parallel::UserAgent->new();  
$ua->agent("Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt)");  
$ua->nonblock (1);  
$ua->duplicates (1);  
$ua->max_hosts (5); # sets maximum number of locations accessed in parallel
$ua->max_req  (5); # sets maximum number of parallel requests per host

my $max_connects = 3;  
my $cnt = @urls > $max_connects ? $max_connects : @urls;  
add_request() foreach (1 .. $cnt);  

sub add_request {  
    # my $url = shift @urls or return;  
    # my $req = HTTP::Request->new(GET => $url);  
    # $ua->register($req);  
    
    while (scalar (@urls) > 0) {
        my $url = shift (@urls); 
        my $req = HTTP::Request->new (GET => $url);  
        $ua->register($req);
    }
}   

{  
no warnings;  
sub LWP::Parallel::UserAgent::on_return  {  
  my ($self, $request, $response, $entry) = @_;  
  if($response->is_success()) {  
    print "Succeeded for '", $response->request->url, "'\n";  
    
    get_url_from_content ($response -> content);
  }  
  add_request();  
 }  
sub LWP::Parallel::UserAgent::on_failure { add_request() }  
}  
my $entries = $ua->wait ();  



sub get_url_from_content {
    my $content = shift;
    my @pattern1 = ();
    push (@pattern1, 'href="(.+?)"');
    push (@pattern1, 'href=\'(.+?)\'');
    
    my @pattern2 = ();
    push (@pattern2, '/noty.html?'); 
    push (@pattern2, '/noty/.+?.html$'); 
    push (@pattern2, '/uchebniki.html$'); 
    push (@pattern2, '/uchebniki.html?'); 
    push (@pattern2, '/uchebniki/.+?.html$'); 
    
    foreach (@pattern1) {
        while ($content =~ /$_/ig) {
            my $url = $1;
            foreach (@pattern2) {
                if ($url =~ /$_/i) {
                    $url = 'http://libnote.ru'.$url;
                    push (@urls , $url);
                }
            }
        } 
    }
}



Грабит локально с denwera (на этой же машине стоит).
И не выдерживает никакой конкуренции по скорости с грабером на threads, который я думаю написан как раз через жопу на коленке - ибо я наверное по другому и не умею. Вообщем недоволен я остался LWP::Parallel. На Threads Выставил 5 потоков (больше нельзя ибо памяти не хватает smile) и только успевай контент получать - а тут 5 потоков и тормоза - грабит как в 1 поток (может чего в коде не так?).

Может кто поделится кодом с Anyevent::HTTP, чтобы сравнить скорости, уж больно в документации мало примеров ... Спасибо.


--------------------
Нотный архив http://libnote.ru скачать ноты бесплатно
PM MAIL   Вверх
EcSYZ
Дата 13.5.2011, 14:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 79
Регистрация: 21.6.2007

Репутация: нет
Всего: 1



Код

#!/usr/bin/perl
$|=1;
use v5.10;
use strict;
use warnings;
use AnyEvent::HTTP;
$AnyEvent::HTTP::MAX_PER_HOST=4;

my $links=[];
for(1 .. 100){
    push @$links, 'http://localhost/test.pl?id='.$_;
}

my $cv = AnyEvent->condvar;
my $count=0;
 
foreach my $link (@$links){
   $count++;
   http_request(
      GET     => $link,
      headers => { "user-agent" => 'Opera/9.80 (X11; Linux x86_64; U; ru) Presto/2.8.131 Version/11.10' },
      timeout => 5,
      sub {
         #say $_[1]->{Status}." : $count : $link";
         (--$count)==0 ? $cv->send : undef;
   });
}
$cv->recv;

Генериться 100 ссылок.
4 потока:
Код

real    0m3.163s
user    0m0.220s
sys    0m0.035s


10 потоков:
Код

real    0m2.714s
user    0m0.222s
sys    0m0.039s

----------------------
На локалхосте больше 10 коллбэков оказывается без мазы, а для нета работал с 20-40.

Это сообщение отредактировал(а) EcSYZ - 13.5.2011, 14:11
PM MAIL WWW   Вверх
EcSYZ
Дата 13.5.2011, 16:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 79
Регистрация: 21.6.2007

Репутация: нет
Всего: 1



Тоже, но только на threads:
Код

#!/usr/bin/perl
$|=1;
use v5.10;
use strict;
use warnings;
use threads;
use threads::shared;
use Mojo::UserAgent;

my $ua = Mojo::UserAgent->new;
my $links=[];
share($links);
for(1 .. 100){
    push @$links, 'http://localhost/test.pl?id='.$_;
}

for(1 .. 4){
    threads->create(\&run,$_);
}
foreach(threads->list) { $_->join; }

sub run
{
    while(scalar @$links != 0){
        $ua->get(pop @$links);
    }
}


4 потока:
Код

real    0m4.102s
user    0m0.798s
sys    0m0.098s


10 потоков:
Код

real    0m3.881s
user    0m1.157s
sys    0m0.162s


PS: с LWP::UserAgent выходит ещё медленней, примерно на 100-400ms (подсчёт примерный).
PS2: хотел ещё LWP::Parallel::UserAgent затестить, но он у меня даже не собрался ...

Это сообщение отредактировал(а) EcSYZ - 13.5.2011, 16:46
PM MAIL WWW   Вверх
burakov
Дата 16.5.2011, 16:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 554
Регистрация: 28.7.2006

Репутация: нет
Всего: нет



попробовал под себя адаптировать код AnyEvent::HTTP, но не получается... где то ошибка.
почему то колбэк (sub) отрабатывает один раз...
подозреваю, что это из за неправильно расставленных
$cv->send; #???
$cv->recv; #???
Но я так из описания модуля и не нашел этих методов на cpan.org что они делают и как их использовать, чтобы все работало...
А может дело и не в этом...

В чем ошибка? Спасибо.


Код

$|=1;
# use v5.10;

use strict;
use warnings;
use clear_str;
use AnyEvent::HTTP;
$AnyEvent::HTTP::MAX_PER_HOST=4;

my @links = (); 
push @links, 'http://libnote.ru';

my $cv = AnyEvent->condvar;
my $count=0;

while (1) {
    my $link = shift (@links); 
    if (defined $link ) {
        get ($link);
    }
}
 
sub get {
    my $link = shift or return;
    print $link ."\n";
    
    #my $link = shift (@links) or return;
    #print $link ."\n";
  
   http_request (
      GET     => $link,
      headers => { "user-agent" => 'Opera/9.80 (X11; Linux x86_64; U; ru) Presto/2.8.131 Version/11.10' },
      timeout => 5,
      
    sub {
            my ($body, $hdr) = @_;
            $count ++;
            print $_[1]->{Status}." : $count : $link". "\n" ;            
            
            my $content = $body;
            $content = utf8_to_win1251 ($content); 
            my $clear_str = clear_str  -> new ($content); 
            $content = $clear_str -> delete_1 ();
            $content = $clear_str -> delete_4 ();
            $clear_str = undef;
            get_url_from_content ($content);  #ищу и фильрую ссылки и добавляю их к глобал @links

            $cv->send; #???
        }
    );    
    $cv->recv; #???
}



sub get_url_from_content  {
    my $content = shift;
    my @pattern1 = ();
    push (@pattern1, 'href="(.+?)"'); 
    push (@pattern1, 'href=\'(.+?)\''); 
    my @urls = ();
    
    foreach (@pattern1) {
        while ($content =~ /$_/g) {
            push (@urls, $1);
        }
    }
    my @pattern2 = ();
    push (@pattern2, '/noty.html$'); 
    push (@pattern2, '/noty.html?'); 
    push (@pattern2, '/noty/.+?.html$'); 
    
    foreach my $url (@urls) {
        foreach my $str2 (@pattern2) {
            if ($url =~ /$str2/i) {
                my $host = 'http://libnote.ru';
                if ($url !~ /^$host/i) {$url = $host.$url; }
                push (@links, $url);
                # print $url."\n";
            }
        }
    }
}

sub utf8_to_win1251 {
    use Encode qw (encode decode); 
    my $str = shift;
    $str = encode ('cp1251', decode ('utf8', $str)); 
    return $str;
}




--------------------
Нотный архив http://libnote.ru скачать ноты бесплатно
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl: CGI программирование"
korob2001
sharq
  • В этом разделе обсуждаются вопросы относящиеся только к CGI программированию
  • Если ваш вопрос не относится к системному или CGI программированию, задавайте его в общем разделе
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", качать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: разработка для Web | Следующая тема »


 




[ Время генерации скрипта: 0.0581 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.