More Related Content
Similar to Perl 非同期プログラミング
Similar to Perl 非同期プログラミング(20)
Perl 非同期プログラミング
- 1. 非同期プログラミング
with Perl
2010/08/07
Japan Perl Association 代表理事
株式会社ライブドア
牧 大 輔 (@lestrrat)
- 3. 普通の書き方
use strict;
use LWP::UserAgent;
my @urls = qw(
http://www.livedoor.com/
http://www.dena.jp/
http://mixi.jp/
http://www.gaiax.co.jp/
);
my $ua = LWP::UserAgent->new();
foreach my $url (@urls) {
my $res = $ua->get( $url );
...
}
- 11. 効率よくread
読める? ソケット1
(データ来た?)
ソケット2
ソケット3
- 12. 効率よくread
ソケット1
読める? ソケット2
(データ来た?)
ソケット3
- 13. 効率よくread
ソケット1
ソケット2
読める? ソケット3
(データ来た?)
- 14. 効率よくread
ソケット1
ソケット2
読める?
来た! ソケット3
(データ来た?)
読み込め!
- 17. 効率よくread
読める?
来た! ソケット1
(データ来た?)
読み込め!
ソケット2
- 20. 効率よくread
来た!
読める? ソケット2
読み込め!
(データ来た?)
- 25. イベントループ
=
while ( $still_alive ) {
... 処理 ...
}
- 27. イベントループ キュー
コールバック 実行!
コールバック
コールバック
コールバック
このイベントを待っている
イベント発生!
コールバックがあるか確認
- 34. 汎用API これだけ覚えていればOK
AnyEvent
デフォルト
Event
その他
Glib
POE
EV
- 48. I/O
my $io;
$io = AE::io $fh, $read_or_write, sub {
.... # $fhから読んだり、$fhに書いたり
undef $io;
};
注意:$fhは非同期モードに指定しておく
- 56. NG
{
my $timer = AE::timer 0, 1, sub {
warn “timer invoked”; # 走らない!
};
} # ここにたどり着いた時点で $timerが解放
スコープ終了。リソース解放され
$timerも解放されてしまう
- 57. Good
my $timer;
$timer = AE::timer 0, 1, sub {
... # どこかで $timer を使うコード
undef $timer; # 明示的に解放しないと消えない
}
クロージャで使用されているため
明示的に解放されるまで生き残る
- 60. #!perl
use strict;
use AnyEvent;
my $cv = AE::cv {
print "Endn";
};
my $timer;
$timer = AE::timer 10, 0, sub {
print "Waited 10 seconds!n";
undef $timer;
$cv->send;
};
$cv->recv;
- 61. #!perl
use strict;
use AnyEvent;
my $cv = AE::cv {
print "Endn";
};
my $timer;
$timer = AE::timer 10, 0, sub {
print "Waited 10 seconds!n";
undef $timer;
$cv->send;
};
$cv->recv;
知らせ が来るまでこの次にはいかない
(→イベントループが起動)
- 62. #!perl
use strict;
use AnyEvent;
my $cv = AE::cv {
print "Endn";
};
my $timer;
$timer = AE::timer 10, 0, sub {
print "Waited 10 seconds!n";
undef $timer;
$cv->send; タイマーが起動したら 知らせ を送る
};
$cv->recv;
- 63. #!perl
use strict;
use AnyEvent;
my $cv = AE::cv {
print "Endn";
};
my $timer;
$timer = AE::timer 10, 0, sub {
print "Waited 10 seconds!n";
undef $timer;
$cv->send;
};
$cv->recv;
知らせ が来たら次の処理へ
(→スクリプト終了)
- 64. #!perl
use strict;
use AnyEvent;
my $cv = AE::cv {
print "Endn";
};
my $timer;
$timer = AE::timer 10, 0, sub {
print "Waited 10 seconds!n";
undef $timer;
$cv->send;
};
$cv->recv;
- 69. #!perl
use strict;
use AnyEvent;
my @delay = (1, 2, 5, 10);
my $cv = AE::cv { print "All timers are donen" };
foreach my $delay (@delay) {
my $timer;
$cv->begin;
$timer = AE::timer $delay, 0, sub {
print "Timer for delay = $delayn";
undef $timer;
$cv->end;
};
}
$cv->recv;
- 70. #!perl
use strict;
use AnyEvent;
my @delay = (1, 2, 5, 10);
my $cv = AE::cv { print "All timers are donen" };
foreach my $delay (@delay) {
my $timer;
$cv->begin; フラグをあげる
$timer = AE::timer $delay, 0, sub {
print "Timer for delay = $delayn";
undef $timer;
$cv->end;
};
}
$cv->recv;
- 71. #!perl
use strict;
use AnyEvent;
my @delay = (1, 2, 5, 10);
my $cv = AE::cv { print "All timers are donen" };
foreach my $delay (@delay) {
my $timer;
$cv->begin;
$timer = AE::timer $delay, 0, sub {
print "Timer for delay = $delayn";
undef $timer;
$cv->end; フラグを落とす
};
}
$cv->recv;
- 72. #!perl
use strict;
use AnyEvent;
my @delay = (1, 2, 5, 10);
my $cv = AE::cv { print "All timers are donen" };
foreach my $delay (@delay) {
my $timer;
$cv->begin;
$timer = AE::timer $delay, 0, sub {
print "Timer for delay = $delayn";
undef $timer;
$cv->end;
};
}
$cv->recv; フラグが全部落ちたらお知らせ
- 73. #!perl
use strict;
use AnyEvent;
my @delay = (1, 2, 5, 10);
my $cv = AE::cv { print "All timers are donen" };
foreach my $delay (@delay) {
my $timer;
$cv->begin;
$timer = AE::timer $delay, 0, sub {
print "Timer for delay = $delayn";
undef $timer;
$cv->end;
};
}
$cv->recv;
- 74. 3. 処理終了時の
コールバック
•何か戻り値が必要な時処理結果を待つ
•ウォッチャーを作る関数に知らせて欲
しいcondvarを渡す
- 75. #!perl
use strict;
use AnyEvent;
sub add {
my ($x, $y, $cv) = @_;
my $timer;
$timer = AE::timer 5, 0, sub {
$cv->send( $x + $y );
undef $timer;
};
}
my $cv = AE::cv {
my $cv = shift;
my ($result) = $cv->recv;
print "Result = $resultn";
};
add( 3, 2, $cv );
$cv->recv;
- 76. #!perl
use strict;
use AnyEvent;
sub add {
my ($x, $y, $cv) = @_;
my $timer;
$timer = AE::timer 5, 0, sub {
$cv->send( $x + $y );
undef $timer;
};
}
my $cv = AE::cv {
my $cv = shift;
my ($result) = $cv->recv;
print "Result = $resultn";
};
add( 3, 2, $cv ); 結果を受け取るコールバックを渡す
$cv->recv;
- 77. #!perl
use strict;
use AnyEvent;
sub add {
my ($x, $y, $cv) = @_;
my $timer;
$timer = AE::timer 5, 0, sub {
$cv->send( $x + $y ); 計算結果をcondvarに渡す
undef $timer;
};
}
my $cv = AE::cv {
my $cv = shift;
my ($result) = $cv->recv;
print "Result = $resultn";
};
add( 3, 2, $cv );
$cv->recv;
- 78. #!perl
use strict;
use AnyEvent;
sub add {
my ($x, $y, $cv) = @_;
my $timer;
$timer = AE::timer 5, 0, sub {
$cv->send( $x + $y );
undef $timer;
};
}
my $cv = AE::cv {
my $cv = shift;
my ($result) = $cv->recv; 結果を受け取る
print "Result = $resultn";
};
add( 3, 2, $cv );
$cv->recv;
- 79. #!perl
use strict;
use AnyEvent;
sub add {
my ($x, $y, $cv) = @_;
my $timer;
$timer = AE::timer 5, 0, sub {
$cv->send( $x + $y );
undef $timer;
};
}
my $cv = AE::cv {
my $cv = shift;
my ($result) = $cv->recv;
print "Result = $resultn";
};
add( 3, 2, $cv );
$cv->recv;
- 83. use strict;
use AnyEvent;
use AnyEvent::HTTP;
my @urls = qw(
http://www.livedoor.com/
http://www.dena.jp/
http://mixi.jp/
http://www.gaiax.co.jp/
);
my $cv = AE::cv {
print "Fetched all urls!n";
};
my $guard;
foreach my $url (@urls) {
$cv->begin;
$guard = http_get $url, sub {
print "Got $urln";
undef $guard;
$cv->end;
}
}
$cv->recv;
- 85. ライブラリ
AnyEvent::Twitter AnyEvent::Memcached AnyEvent::FriendFeed::Realtime
AnyEvent::Twitter::Stream AnyEvent::ReverseHTTP AnyEvent::HTTP::MXHR
AnyEvent::CouchDB AnyEvent::SuperFeedr AnyEvent::AIO
AnyEvent::BDB AnyEvent::DNS AnyEvent::Beanstalk
AnyEvent::DBI AnyEvent::SNMP AnyEvent::MP
AnyEvent::Gearman AnyEvent::XMPP Cache::Memcached::AnyEvent
- 89. ちょっとずつレスポンス
use strict;
use AnyEvent;
sub {
my $env = shift;
return sub {
my $start_response = shift;
my $writer = $start_response->( [
200,
[ "Content-Type" => "text/plain" ]
]);
my $count = 1;
my $t; $t = AE::timer 2, 2, sub {
$writer->write( ($count * 2) . "秒たったよ!n");
if ($count++ == 5) {
undef $t;
$writer->close;
}
};
}
}
- 90. 用途
非同期サーバー
•接続後切断しない or •何らかのイベント待っている
•いつ来るかわからないデー •メッセージキュー、速いか遅
タを待っている いかわからないサービス等
- 94. 非同期にする条件
• リアルタイム性が重要
• いつ起こるか分からない
•ポーリングではリクエスト回数が多すぎる
• I/O待ちが多い
•データを常時送り続けているのは x
•待ち時間が長いとメリットがある