Your SlideShare is downloading. ×
0
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Perl 非同期プログラミング
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Perl 非同期プログラミング

16,593

Published on

Published in: Technology
1 Comment
27 Likes
Statistics
Notes
  • Perlでの非同期プログラミングについて、関連モジュールと汎用ラッパとしてのAnyEventの存在から、実際のプログラミングのツボまでをまとめている。++。
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
16,593
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
0
Comments
1
Likes
27
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Transcript

    • 1. 非同期プログラミング with Perl 2010/08/07 Japan Perl Association 代表理事 株式会社ライブドア 牧 大 輔 (@lestrrat)
    • 2. さっそくですが 「複数URLに接続してHTTP GETするコード」
    • 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 );   ...}
    • 4. ポイント•シンプル!•命令を順番に処理•ソケットからの読み込みに時間がかかると次の処理に進めない
    • 5. 理想•とりあえず可能な限りのホストに接続•接続できたらとりあえずHTTPリクエスト発行•読み込み可能なところ(先に返信が来たところから)読み込む
    • 6. read•read(2) は読み込めるデータが到着するまでブロックする•一個だけ遅いホストがあると全体が遅くなる :/
    • 7. 効率よくread
    • 8. 効率よくread ソケット1
    • 9. 効率よくread ソケット1 ソケット2
    • 10. 効率よくread ソケット1 ソケット2 ソケット3
    • 11. 効率よくread 読める? ソケット1 (データ来た?) ソケット2 ソケット3
    • 12. 効率よくread ソケット1 読める? ソケット2 (データ来た?) ソケット3
    • 13. 効率よくread ソケット1 ソケット2 読める? ソケット3 (データ来た?)
    • 14. 効率よくread ソケット1 ソケット2 読める? 来た! ソケット3 (データ来た?) 読み込め!
    • 15. 効率よくread ソケット1 ソケット2 読める? (データ来た?)
    • 16. 効率よくread 読める? ソケット1 (データ来た?) ソケット2
    • 17. 効率よくread 読める? 来た! ソケット1 (データ来た?) 読み込め! ソケット2
    • 18. 効率よくread 読める? (データ来た?) ソケット2
    • 19. 効率よくread 読める? ソケット2 (データ来た?)
    • 20. 効率よくread 来た! 読める? ソケット2 読み込め! (データ来た?)
    • 21. 効率よくread 読める? (データ来た?)
    • 22. 効率よくread
    • 23. イベント駆動
    • 24. メインループ(プログラムの進行) を他人に任せる
    • 25. イベントループ = while ( $still_alive ) { ... 処理 ... }
    • 26. ループから呼ばれるコールバックを登録する
    • 27. イベントループ キュー コールバック 実行! コールバック コールバック コールバック このイベントを待っているイベント発生! コールバックがあるか確認
    • 28. イベント?非同期?• イベント駆動の仕組みの中でI/O処理→ファイルハンドル等を「非同期モード」にする• イベント駆動のメリットを生かすにはI/O等ブロックする処理が多いときに使う•よって「非同期プログラミング」と「イベント駆動プログラミング」は同義で使うことが多い
    • 29. AnyEvent
    • 30. なんで?
    • 31. POEDanga::SocketIO::AsyncEventGlib Qt
    • 32. お互いに互換性無し
    • 33. AnyEvent非同期フレームワークのラッパ
    • 34. 汎用API これだけ覚えていればOK AnyEventデフォルト Event その他 Glib POE EV
    • 35. standard API++
    • 36. 混ぜることもできる 例:POE+EV
    • 37. 新規に書くならAnyEventでおk
    • 38. 先にお知らせ
    • 39. 名前空間
    • 40. AnyEvent vs AE
    • 41. スタイルの違いだけAnyEvent->timer(    after => $after,    interval => $interval,    cb => sub {        ....    });AE::timer $after, $interval, sub {    ...};
    • 42. ここではAEを 使います
    • 43. 基本コンポーネント•ループ•ウォッチャー•コンディション変数•ガード
    • 44. ウォッチャー
    • 45. AnyEventコンポーネント IO コールバック 実行! タイマー コールバック 「ウォッチャー」
    • 46. AnyEventを使う = ウォッチャーの管理をする
    • 47. Timermy $timer;$timer = AE::timer 0, 1, sub {    warn “timer invoked”;    undef $timer;};
    • 48. I/Omy $io;$io = AE::io $fh, $read_or_write, sub {    .... # $fhから読んだり、$fhに書いたり    undef $io;}; 注意:$fhは非同期モードに指定しておく
    • 49. fh_nonblockinguse AnyEvent::Util qw(fh_nonblocking);my $fh = get_socket(...);fh_nonblocking $fh, 1;my $io;$io = AE::io $fh, 0, sub { ... };
    • 50. シグナルmy $sig;$sig = AE::signal "TERM", sub { ...    undef $sig;};
    • 51. 子プロセスmy $child;$child = AE::child $pid, sub {    ...    undef $child;};
    • 52. 待機状態my $idle;$idle = AE::idle sub {    ...    undef $idle;};
    • 53. なにこれ?my $timer;$timer = AE::timer 0, 1, sub {    warn “timer invoked”;    undef $timer;};
    • 54. Perl:スコープが終わるとメモリが解放される
    • 55. AnyEvent:ウォッチャーが解放されるとイベントがキャンセルされる
    • 56. NG{    my $timer = AE::timer 0, 1, sub {        warn “timer invoked”; # 走らない!    };} # ここにたどり着いた時点で $timerが解放 スコープ終了。リソース解放され $timerも解放されてしまう
    • 57. Goodmy $timer;$timer = AE::timer 0, 1, sub {    ... # どこかで $timer を使うコード    undef $timer; # 明示的に解放しないと消えない} クロージャで使用されているため 明示的に解放されるまで生き残る
    • 58. コンディション変数• いくつかの違う機能が同居してる• ちょっと混乱しやすい• が、重要• 以降 「condvar」と表記
    • 59. 1. 何かを待つ•現処理の流れを「止める」•「知らせ」を待つ•スクリプトレベルでは「ループに制御を渡す」
    • 60. #!perluse 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. #!perluse 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. #!perluse 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. #!perluse 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. #!perluse 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;
    • 65. #!perluse strict;use AnyEvent;my $timer;$timer = AE::timer 10, 0, sub {   print "Waited 10 seconds!n";   undef $timer;};
    • 66. #!perluse strict;use AnyEvent;my $timer;$timer = AE::timer 10, 0, sub {   print "Waited 10 seconds!n";   undef $timer;}; 何も「待つ」ことがなかったので イベントループも起動しない
    • 67. #!perluse strict;use AnyEvent;my $timer;$timer = AE::timer 10, 0, sub {   print "Waited 10 seconds!n";   undef $timer;};
    • 68. 2. 複数の知らせを待つ•フラグをあげる→落とす•一つでもフラグがあがっていれば待つ•フラグが全部落ちるとお知らせ
    • 69. #!perluse 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. #!perluse 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. #!perluse 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. #!perluse 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. #!perluse 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. #!perluse 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. #!perluse 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. #!perluse 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. #!perluse 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. #!perluse 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;
    • 80. 基本はこれだけ•ウォッチャーとcondvarだけで基本的に全てまかなえる•実際にはこれらを使った高レベルライブラリを使う
    • 81. AnyEventで 「複数URLに接続してHTTP GETするコード」
    • 82. AnyEvent::HTTP
    • 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;
    • 84. 以上!•万が一どれかが遅くても、他のURLは先に処理される
    • 85. ライブラリ AnyEvent::Twitter AnyEvent::Memcached AnyEvent::FriendFeed::RealtimeAnyEvent::Twitter::Stream AnyEvent::ReverseHTTP AnyEvent::HTTP::MXHR AnyEvent::CouchDB AnyEvent::SuperFeedr AnyEvent::AIO AnyEvent::BDB AnyEvent::DNS AnyEvent::Beanstalk AnyEvent::DBI AnyEvent::SNMP AnyEvent::MPAnyEvent::Gearman AnyEvent::XMPP Cache::Memcached::AnyEvent
    • 86. TwiggyPlack用非同期HTTPサーバー
    • 87. 1 スレッド!複数接続高速処理
    • 88. plackup -s Twiggy ...
    • 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 •何らかのイベント待っている•いつ来るかわからないデー •メッセージキュー、速いか遅タを待っている いかわからないサービス等
    • 91. プロキシ•外部サーバーと連携するサービス •サーバーの性能を自分でコントロールできな い場合など•某SNSとか某SNSとか
    • 92. イベントサーバー•ブラウザゲーム•複数のクライアントが同時にイベントを共有する場合など
    • 93. 注意•「やりたいから」非同期にすると失敗する•「必要があるから」使うべき•非同期コードは難しくなる
    • 94. 非同期にする条件• リアルタイム性が重要 • いつ起こるか分からない •ポーリングではリクエスト回数が多すぎる• I/O待ちが多い •データを常時送り続けているのは x •待ち時間が長いとメリットがある
    • 95. 非同期にしない理由•コードが複雑になる•コードが複雑になる•コードが複雑になる•コードが複雑になる•コードが複雑になる
    • 96. 必要な時だけ使う =効果絶大
    • 97. Questions?
    • 98. ご静聴ありがとう ございました

    ×