マルチタスクって奥が深い
OGATA Tetsuji (@xtetsuji)
2014/07/12 Mishima.pm#1
自己紹介
• 尾形 鉄次 (OGATA Tetsuji)
• Twitter: @xtetsuji
• Blog: http://post.tetsuji.jp/
今回は無事に静岡に来られた!
2013/12/11 Mishima.pm#0
2013年12月に胃潰瘍で入院したときのツイートまとめ -
Togetterまとめ http://togetter.com/li/607049
あれから半年
• 半年経過後の胃カメラ検査をつい先日してきました
• 静岡前の胃カメラ、今度は死亡フラグじゃなかった
• 珍しい位置の潰瘍だったけど、なんとか生きてます
• あれから毎月激動で、公私ともに忙しいけれど、皆様の
温かいご支援で生きています
今だから復習したい
マルチタスク
過去にもマルチタスクの話は
結構しているけど成長が(ry
過去にしているトークの一例
• 「そのsleep、ちょっと待った」(PerlBeginners#13)
• 「イベント駆動とノンブロッキング」(Hokkaido.pm#10)
• 今回はこれらのプラスアルファな感じの話をします
• ビギナー向けにちょうどよい感じ、という言い訳
• みんなで質疑応答をしたりといった感じでよろしくです
色々なPerlのツール
• forkや、Parallel::ForkManager、Parallel::Prefork など
• 封印されしithreads (アッ、誰か来た)
• AnyEvent前史のPOEフレームワーク
• AnyEvent、そしてCoroといったMarc Lehmmanツール
• 今昔IO非同期系ツール群
結構雑にカジュアルに
• マルチタスク=複数の仕事をこなす
• 非同期=ノンブロッキング
• 同期=ブロッキング
• 情報系の学術論文でないのであれば、この辺りあんまり
厳密に区別しなくてもよいっぽい(頭の中でできることに
越した事はありません)
ithreadsが使われない理由
• Perlのスレッド(ithreads)は不安定だし効率が悪い
• Perlはグローバルな状態だらけの世界観なので、後付け
のスレッドもインタープリタプールを作ったり、色々大
変な事をしているので、同情してあげてください
• Windowsにはforkがないので、WindowsのPerlでは
Win32スレッドを使ったforkのエミューレーションをし
ているそうです
forkモデル
• fork=フォーク=分岐
• 途中で親と子に分かれてプログラムの分岐を行う
• Perl組み込みのfork関数がそれを実現してくれる
forkサンプル
#!/usr/bin/env perl!
!
use strict;!
use warnings;!
use utf8;!
!
binmode STDOUT, ':utf8';!
binmode STDERR, ':utf8';!
!
print "親です。プロセスIDは $$ です。開始します。n";!
!
my $pid = fork; # ここで親と子で分岐!
!
if ( $pid ) {!
sleep 2;!
print "親です。子のプロセスIDは $pid のようです。しばらく休みますn";!
sleep 10;!
print "親です。10秒待ちました。n";!
} elsif ( $pid == 0 ) {!
sleep 3;!
print "子です。私のプロセスIDは $$ のようです。n";!
for my $i (1..5) {!
print "子です。${i}回目。n";!
sleep 1;!
}!
print "子はしばらく待ちます。先に親が終了してプロンプトに戻りますn";!
sleep 10;!
} else {!
die "forkできなかった?n";!
}!
!
print "pid=$pid $$=$$n"; # 親も子も通る
あんまりforkを直接書かない
• 見てパッと理解できない
• 多くの子プロセスを作るときにfork()を呼びまくった
ら結構混乱する
• 親と子でコミュニケーションするにはプロセス間通信が
一番プリミティブな方法かな
• 多くのforkが必要になった場合には、これを抽象化した
Parallel::ForkManagerが役に立つ
Parallel::ForkManagerの例
#!/usr/bin/env perl!
!
use strict;!
use warnings;!
!
use LWP::UserAgent;!
use Parallel::ForkManager;!
!
my @urls = ( map { sprintf "http://example.jp/images/%02d.jpg" } (1..99) );!
!
my $ua = LWP::UserAgent->new;!
!
my $pm = Parallel::ForkManager->new(5); # 最大5プロセス並列!
!
for my $url (@urls) {!
my $pid = $pm->start and next;!
# 子プロセスの処理!
print "プロセスIDが $$ の子プロセスが $url からデータをダウンロードしますn";!
( my $filename = $url ) =~ s{.*/}{};!
$ua->get($url, ":content_file" => $filename);!
$pm->finish; # 子プロセスを終了!
}
並列ダウンロードと
マルチタスク
• 外界の影響を受けるダウンロードというタスクの場合、
同期的にダウンロードをするとサーバによって待たされ
るケースがあったりする
• RSSとかを大量にクロールするとか、死活問題
• 例えばParallel::ForkManagerで解決できる
ForkManagerとPrefork
• Parallel::ForkManagerは並列クライアントを作るもの、
Parallel::Preforkは並列処理ができるforkモデルのサーバ
を作るものと覚えておくとよい
• Parallel::ForkManagerは相当以前からDebian/Ubuntu
パッケージとしても提供されているので、システムPerl
でも使いやすい
• Parallel::Preforkは奥一穂さんによる和製モジュール
forkの問題点と言われること
• プログラムのコピーなのでメモリを食う
• Copy on Write(CoW)というOSの機構により倍々には
ならないはずだけど、限界はある
• プロセス間通信が面倒
• これは頑張るか、コストを気にしなければHTTP等の
サーバを介したりするのがよいかも
とはいえforkはよく使う
• UNIX/Linuxのサブプロセスの原点fork
• 覚えておくと色々勉強になるし、自分もよく勉強してる
• Perlのsystem関数はforkとexecの組み合わせ
• 先輩プログラマが「フォーク」とか言っているときに、
ちょっと知った気になれるの重要
イベント駆動モデル
• スレッドともforkとも若干違うマルチタスクモデル
• Apacheのprefork MPMがAjax時代にまつわるC10K問題
に対抗できない代替として生まれたともいえるNginxの
マルチタスクモデルとして注目された
• Perlでは、AnyEventというイベント駆動フレームワーク
が以前から主流で、以前からあった同種のイベント駆動
モジュールのインターフェースを統一したりもした
AnyEvent
• 以前流行したPOEの後継にあたるものともいえる
• Perlで動作する様々なイベント駆動フレームワークの、
今の事実上のデファクトスタンダード
• 裏側のイベント処理実装に様々なものが選べる
• 各種イベント(時間、I/O、シグナル、などなど)で処理を
走らせることができる
AnyEventの後ろの実装
• AnyEvent::Impl::* 以下にあるものが選べる
• Cocoa、Event、FLTK、IOAsync、POE、Qt、EV、
EventLib、Glib、Irssi、Perl (AnyEvent標準の実装)、Tk
• 通常はAnyEvent::Impl::Perlが選ばれるけど、EVを選ん
だり、場所によって選択を変える場合がある
• Marc Lehmann氏も「POEはやめとけ」と書いている
POEが衰退した理由
• 構造が複雑:OSとほぼ同じ、カーネル・ヒープ構造
• 書き方が複雑
• 静かにプログラムが異常終了していることが多かった
• 重いとも言われていた
daemonを作るwhileループ
• daemon的な常駐プログラムを作る場合、

while(1){…} といった無限ループを作ることが定石
• とはいえ、無限ループにsleepをはさみ忘れたりすると、
CPU暴走してサーバが死んだりするので怖い
• while無限ループはなるべく自前で書かない方がいいとい
うのが私の持論
AnyEventの方法論
• AnyEvent::Impl::* によっても変わるけど、結局的に、
PerlやCのwhile(1){…}が一番根底で走っていると思っ
て差し支えない
• 特にAnyEvent::Impl::Perlの場合は、AnyEvent::Loopが
それらしい
AnyEvent::Loopより
sub run {!
one_event while 1;!
}
one_event メソッドは多くの仕事をしていますが割愛
AnyEventの活用例
• クライアントでは各種IRCやTwitterボットなどで活用
• サーバではWebサーバ(Twiggyが有名)をはじめとした、
任意のTCPサーバが書ける
• これらを組み合わせたりできるので、IRCクライアント
でかつWebサーバというプログラムも書ける (Ikachanと
いう良い実装例もある)
AnyEventで時間イベント
#!/usr/bin/env perl!
!
use strict;!
use warnings;!
use AnyEvent;!
!
my $cv = AnyEvent->condvar; # 状態変数!
my $timer1 = AnyEvent->timer(!
after => 1,!
cb => sub { print "timer1 hello!n"; },!
interval => 2,!
);!
my $timer2 = AnyEvent->timer(!
after => 1,!
cb => sub { print "timer2 hello!n"; },!
interval => 3,!
);!
my $timer3 = AnyEvent->timer(!
after => 1,!
cb => sub { print "timer3 hello!n"; },!
interval => 5,!
);!
my $stop_timer = AnyEvent->timer(!
after => 10,!
cb => sub { $cv->send("end"); }, # 終わらせる!
);!
my $val = $cv->recv; # ループをまわす!
print "terminate: $valn";
AnyEventで時間イベント
• 最初はwhileループのほうが良いと思うけど、自分で気を
つけてsleep書かなくてもいいし慣れるとこっちが良い
• IRCボットとかだと、定時発言などもこれでできる
• perldoc AnyEventをみたり、CPANでAnyEventで作られ
たモジュールを見たりして少しずつ覚えていくといい
AnyEvent::Mac::Pasteboard
• Macのクリップボード(ペーストボード)を監視して、変更
があったら指定の処理をするモジュールを書いてみた
• これもタイマーで変更を定期監視しているだけ
• Cocoaの知識があればもっと良い感じができるかも
• その後AnyEvent::Clipboardも作りました(GitHub止まり)
その他
• CPANで「Async」というキーワードで検索してみる
• AnyEventを入れるほどではないけど、非同期アクセスが
必要な場合に良い場合がある (HTTP::Asyncとか)
• MojoliciousであればMojo::IOLoopとか
• Mojolicious飲み会とかやりたいと思っているので、続き
はそこで非同期飲み会やりましょう
注意点とか
• LWP::UserAgent等で長時間処理をブロックしたりする
と、AnyEventの処理全体をブロックすることになるので
ノンブロッキングなAnyEvent::HTTPなどを使おう
• JavaScriptのAjaxやっている人だとコールバック的
• ドヤ顔で「AnyEventで(ry」とか言ってIO::Socket::INET
使っていたりすると、ブロッキングとか言われて恥ずか
しい思いをします
最後にいろいろ
• ノンブロッキングのネットワークI/Oについては
AnyEvent::Socketをベースに作ります
• AnyEvent::SocketはSocketモジュールをベースに、ノン
ブロッキングネットワークI/Oの方法論を元に書かれてい
るようです
• 基本的に、既に作られているL7層のモジュールを元に、
自分で新しいプログラムやモジュールを作ればしあわせ
全然掘り起こせなかったですが
奥が深いので続きはどこかで
おしまい

More Related Content

PDF
CD-ROMドライブを身につけよう
PDF
20151114 jawsug
PDF
Making Editor written in Ruby version 20160611
PDF
Goodpatchに生息するbotたち
PPTX
新卒3年目のぼくが、でぶおぷす???なインフラおじさん方にAnsibleを導入してみた
PDF
GUI何処行ったんDocker
PDF
20121126 Solr@ニコニコ生放送
PPTX
LT駆動開発08 - 無限のディスク領域を手に入れよう(妄想編)
CD-ROMドライブを身につけよう
20151114 jawsug
Making Editor written in Ruby version 20160611
Goodpatchに生息するbotたち
新卒3年目のぼくが、でぶおぷす???なインフラおじさん方にAnsibleを導入してみた
GUI何処行ったんDocker
20121126 Solr@ニコニコ生放送
LT駆動開発08 - 無限のディスク領域を手に入れよう(妄想編)

What's hot (16)

ODP
etckeeperをopenSUSEの公式リポジトリに入れたいぞ! Ver.2
PDF
Goodby Hatena, hello Sphinx
PDF
JVM上で動くPython処理系実装のススメ
PDF
ほんとはこわくない Gentoo Linux
PDF
Gentooサークル新歓コンパのご案内
PDF
俺のGentooがこんなに可愛いわけがない
PDF
Pythonが動く仕組み(の概要)
PDF
Ubuntu なひととき
PDF
マウスを使わないでキーボードで快適に生活する方法(GNU Screen/tmux/byobu/awesome)
ODP
PDF
エンジニアのための痔の話
PPTX
HLSについて知っていることを話します
PPTX
自動テスト入れてみたけど、誰からも反応が無かった話。
PDF
今最もアツイdistribution Gentoo Linuxについて
PDF
S2s websrv201011-presen
PDF
At least onceってぶっちゃけ問題の先送りだったよね #kafkajp
etckeeperをopenSUSEの公式リポジトリに入れたいぞ! Ver.2
Goodby Hatena, hello Sphinx
JVM上で動くPython処理系実装のススメ
ほんとはこわくない Gentoo Linux
Gentooサークル新歓コンパのご案内
俺のGentooがこんなに可愛いわけがない
Pythonが動く仕組み(の概要)
Ubuntu なひととき
マウスを使わないでキーボードで快適に生活する方法(GNU Screen/tmux/byobu/awesome)
エンジニアのための痔の話
HLSについて知っていることを話します
自動テスト入れてみたけど、誰からも反応が無かった話。
今最もアツイdistribution Gentoo Linuxについて
S2s websrv201011-presen
At least onceってぶっちゃけ問題の先送りだったよね #kafkajp
Ad

Viewers also liked (8)

PDF
東京近郊のPerlコミュニティのご紹介 #lcs2015
PDF
今に伝えるメールの技術 #yapcasia #yapcasiareject
PDF
2014年には役に立たないセッションの昔話 #hachiojipm
PDF
Mojolicious+redisでチャットを作った
PDF
イベント駆動とノンブロッキング #hokkaidopm
PPTX
Stream2の基本
PDF
Joe Emison - 10X Product Development
PDF
DevOpsとか言う前にAWSエンジニアに知ってほしいアプリケーションのこと
東京近郊のPerlコミュニティのご紹介 #lcs2015
今に伝えるメールの技術 #yapcasia #yapcasiareject
2014年には役に立たないセッションの昔話 #hachiojipm
Mojolicious+redisでチャットを作った
イベント駆動とノンブロッキング #hokkaidopm
Stream2の基本
Joe Emison - 10X Product Development
DevOpsとか言う前にAWSエンジニアに知ってほしいアプリケーションのこと
Ad

Similar to マルチタスクって奥が深い #mishimapm (15)

PPTX
Osoljp201204
PDF
初心者がOpenIndianaで自宅サーバを作ったよって話
PDF
プロセスの永続化でコスト削減 #perlbeginners
PDF
チケット管理システム大決戦第二弾
PPTX
システムパフォーマンス勉強会#4
PPTX
システムパフォーマンス勉強会#4
PDF
Frequency with nltk
PPT
appengine活用事例資料@TDDBC札幌2.1
PPTX
Minio on Raspberry Pi
PDF
設定ファイルに使われそうなデータ形式
ODP
etckeeperをopenSUSEの公式リポジトリに入れたいぞ!
KEY
PerlのTwitterモジュールの紹介 #twtr_hack
PDF
第六回 #渋谷java Javaを書き始めて 1年半が経って思うこと
PDF
誰でも出来るosxでのローカルなウェブ開発環境構築
PDF
MF GeeksNight pplogの話
Osoljp201204
初心者がOpenIndianaで自宅サーバを作ったよって話
プロセスの永続化でコスト削減 #perlbeginners
チケット管理システム大決戦第二弾
システムパフォーマンス勉強会#4
システムパフォーマンス勉強会#4
Frequency with nltk
appengine活用事例資料@TDDBC札幌2.1
Minio on Raspberry Pi
設定ファイルに使われそうなデータ形式
etckeeperをopenSUSEの公式リポジトリに入れたいぞ!
PerlのTwitterモジュールの紹介 #twtr_hack
第六回 #渋谷java Javaを書き始めて 1年半が経って思うこと
誰でも出来るosxでのローカルなウェブ開発環境構築
MF GeeksNight pplogの話

More from 鉄次 尾形 (20)

PDF
Perl入学式 2018年度の報告
PDF
【公開版】AWS基礎 for 新卒エンジニア
PDF
俺のこだわりデスクのその後
PDF
Hokkaido.pmと7年
PDF
WordPress 運用を支える Perl
PDF
障害対応とその防止策
PDF
働きやすい社内を目指す!二酸化炭素計測ツール
PDF
Perl ウェブ開発の中世〜CGI と Plack の間〜
PDF
コードの動的生成のお話
PDF
三角関数の加法定理はなぜ難しいのか
PDF
Perlで生きる10年
PDF
穏やかにファイルを削除する続き
PDF
日本全国ぶらりPerl旅
PDF
穏やかにファイルを削除する
PDF
最近のメールまわりのお仕事のお話
PDF
再帰、漸化式、差分方程式とアルゴリズム Gx#20
PDF
超小規模環境のMySQL #mysqlcasual
PDF
mod_perlプログラマーがYAPCで語るレガシー開発論
PDF
4月16日だからFoursquare 位置情報とライフログ
PDF
ライフログ、時系列メモ
Perl入学式 2018年度の報告
【公開版】AWS基礎 for 新卒エンジニア
俺のこだわりデスクのその後
Hokkaido.pmと7年
WordPress 運用を支える Perl
障害対応とその防止策
働きやすい社内を目指す!二酸化炭素計測ツール
Perl ウェブ開発の中世〜CGI と Plack の間〜
コードの動的生成のお話
三角関数の加法定理はなぜ難しいのか
Perlで生きる10年
穏やかにファイルを削除する続き
日本全国ぶらりPerl旅
穏やかにファイルを削除する
最近のメールまわりのお仕事のお話
再帰、漸化式、差分方程式とアルゴリズム Gx#20
超小規模環境のMySQL #mysqlcasual
mod_perlプログラマーがYAPCで語るレガシー開発論
4月16日だからFoursquare 位置情報とライフログ
ライフログ、時系列メモ

マルチタスクって奥が深い #mishimapm