Last active
May 6, 2016 19:46
-
-
Save klopp/975e2e3917f68999f615097c1e13060f to your computer and use it in GitHub Desktop.
Тестовое задание
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
# ------------------------------------------------------------------------------ | |
# Необходимо разработать консольное приложение на базе фреймворка AnyEvent, | |
# которое принимает список URL из STDIN, вызывает их все сразу в | |
# неблокирующем режиме, выводя на экран полученные ответы по мере их получения | |
# и статистику по скорости вызова каждого урла после завершения всех вызовов. | |
# ------------------------------------------------------------------------------ | |
use Modern::Perl; | |
use AnyEvent::Fork; | |
use AnyEvent::Fork::Pool; | |
# ------------------------------------------------------------------------------ | |
use constant DEBUG => 1; | |
# ------------------------------------------------------------------------------ | |
my @links; | |
if (DEBUG) { | |
@links | |
= qw{ http://ya.ru/ http://google.ru/ http://goo.gl/ http://yandex.ru/ }; | |
} | |
else { | |
@links = grep { s/^\s+|\s+$//gs; $_ } <STDIN>; | |
} | |
# ------------------------------------------------------------------------------ | |
my %stat; | |
my $workers = @links; | |
# Хотя, можно и так: | |
# my $workers = AnyEvent::Fork::Pool::ncpu 1; | |
# Не самый удачный вариант с eval. Но тут кода мало, и просто не хочется | |
# создавать отдельный модуль в отдельном файле для require: | |
my $pool = AnyEvent::Fork->new()->eval(' | |
sub _get_url { | |
# На входе URL, на выходе - время его закачки. | |
# Ошибки игнорируем. | |
my ( $url ) = @_; | |
use Modern::Perl; | |
use AnyEvent::HTTP; | |
use Time::HiRes qw/gettimeofday tv_interval/; | |
my $tstart = [gettimeofday]; | |
my $cv = AnyEvent->condvar; | |
http_get $url, sub { | |
my ($body, $hdr) = @_; | |
say $url, q{, status: }, $hdr->{Status}; | |
$cv->send; | |
}; | |
$cv->recv; | |
my $tend = [gettimeofday]; | |
return tv_interval($tstart, $tend); | |
}')->AnyEvent::Fork::Pool::run('_get_url', max => $workers); | |
my $cv = AnyEvent->condvar; | |
my $done = 0; | |
for my $url (@links) { | |
$pool->( | |
$url, | |
sub { | |
$stat{$url} = $_[0]; | |
$done++; | |
$cv->send if $done >= $workers; | |
} | |
); | |
} | |
$cv->recv; | |
say q{}; | |
for (sort { $stat{$a} <=> $stat{$b} } keys %stat) { | |
say "$_ : $stat{$_} sec"; | |
} | |
# ------------------------------------------------------------------------------ | |
# That's All, Folks! | |
# ------------------------------------------------------------------------------ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment