Upload
masaaki-hirose
View
7.043
Download
0
Embed Size (px)
DESCRIPTION
Citation preview
Copyright © KLab Inc. All rights reserved.
2007 年 8 月 6日KLab 株式会社K ラボラトリー廣瀬 正明
非同期 I/O 概説
Introduction to Asynchronous I/OAIO, I/O Multiplexing…
Copyright © KLab Inc. All rights reserved.
今日の目的
非同期 I/O とは何かを知る
非同期 I/O を使うと何がうれしいのかを知る
非同期 I/O を実現する手段(複数)を知る
Copyright © KLab Inc. All rights reserved.
アジェンダ
非同期 I/O を使う理由 非同期 I/O とは? AIO の実装を紹介 AIO の使い方 落穂ひろい
Copyright © KLab Inc. All rights reserved.
アジェンダ
非同期 I/O を使う理由 非同期 I/O とは? AIO の実装を紹介 AIO の使い方 落穂ひろい
Copyright © KLab Inc. All rights reserved.
ネットワークサーバのお仕事を考えてみる
Web サーバとか I/O (ネットワーク I/O 、ディスク I/O )
に着目 リクエストを受ける(ネットワーク read ) ディスクからコンテンツを読む(ディスク re
ad ) レスポンスを返す(ネットワーク write )
Copyright © KLab Inc. All rights reserved.
一般的な I/O の特性
read(2)/write(2) いつでもデータが読める / 書けるとは限らな
い 準備ができるまで戻らない=待たされる
「 I/O ブロッキング」
Copyright © KLab Inc. All rights reserved.
ネットワークサーバ ×I/O
ネットワークサーバ ネットワーク I/O 、ディスク I/O を伴う
I/O ブロッキング I/O で待たされる
単一の処理(リクエスト / レスポンス)を完了するまでに時間がかかる(待たされるので)
単位時間の処理能力が下がる 並行度( concurrent )が下がる
Copyright © KLab Inc. All rights reserved.
The C10K problem
The C10K problem http://www.kegel.com/c10k.html http://www.hyuki.com/yukiwiki/wiki.cgi?TheC10
kProblem “ 「 C10K 問題」(クライアント 1 万台問
題)とは、ハードウエアの性能上は問題がなくても、あまりにクライアントの数が多くなるとサーバがパンクする問題のこと”
同時処理数を上げるための、 I/O 戦略について説明しているドキュメント
Copyright © KLab Inc. All rights reserved.
非同期 I/O
C10K - I/O 戦略
1スレッド:1クライアントで、ブロッキング I/O × 各スレッドでスタックを消費する
NPTL の場合 8MB/thread 1スレッド:多クライアントで、ノンブ
ロッキング I/O (I/O 多重化 ) select, poll, epoll, kqueue, /dev/poll
1スレッド:多クライアントで、 AIO POSIX AIO, libaio
Copyright © KLab Inc. All rights reserved.
アジェンダ
非同期 I/O を使う理由 非同期 I/O とは? AIO の実装を紹介 AIO の使い方 落穂ひろい
Copyright © KLab Inc. All rights reserved.
I/O モデルの整理
Synchronous
Asynchronous
Blocking Non-blocking
read/write read/write(O_NONBLOCK)
I/O multiplexingI/O 多重化
(select, poll)
AIO非同期 I/O
(POSIX AIO, libaio)
~ Boost application performance using asynchronous I/O http://www-128.ibm.com/developerworks/linux/library/l-async/
Copyright © KLab Inc. All rights reserved.
I/O 多重化とは
I/O 可能になった fd の集合を通知するしくみ 通知後に、 read(2),write(2) を行う
実装 select(2)
I/O 可否の検査のためにすべての fd を走査する必要があるので、 fd が多いと効率が悪い
FD_SETSIZE (Linux だと 1024) までしか fd を監視できない poll(2)
FD_SETSIZE の上限がない select(2) epoll(2) Linux, kqueue(2) FreeBSD, /dev/poll Solaris
I/O 可能な fd だけ返却される OS のよって実装がばらばら→ libevent
Copyright © KLab Inc. All rights reserved.
AIO とは
非同期に I/O を行うしくみ 通知時にはすでに read や write が完了している read の場合はバッファにデータが入っている
実装 POSIX AIO
http://opengroup.org/onlinepubs/009695399/basedefs/aio.h.html
Linux, FreeBSD, Mac OS X, Solaris, HP-UX, AIX libaio
http://lse.sourceforge.net/io/aio.html Linux独自の実装
Copyright © KLab Inc. All rights reserved.
I/O 多重化 vs AIO
select(2) はブロックする ※タイムアウトは指定可能
通知後に read(2) が必要=コンテキストスイッチ
Copyright © KLab Inc. All rights reserved.
I/O 多重化 vs AIO
ブロックしない=ほかの処理を行えるシグナルかコールバックが非同期に呼ばれる 通知時には既にバッファに入ってる
Copyright © KLab Inc. All rights reserved.
アジェンダ
非同期 I/O を使う理由 非同期 I/O とは? AIO の実装を紹介 AIO の使い方 落穂ひろい
Copyright © KLab Inc. All rights reserved.
AIO の実装 – Linux 2.6
POSIX AIO – POSIX 準拠 aio_read / aio_write, aio_error, aio_return, … 通知方法は、スレッド( SIGEV_THREAD )とシグナル
( SIGEV_SIGNAL )の両方に対応している 実はシステムコールじゃなくてライブラリ関数( libr
t ) 裏でいくつかスレッドを作ってがんばってるっぽい
libaio – Linux独自 io_queue_init, io_prep_pread / io_prep_pwrite, io_set_c
allback, io_submit, … http://lse.sourceforge.net/io/aio.html システムコール POSIX AIO より性能は上
Copyright © KLab Inc. All rights reserved.
AIO の実装 – FreeBSD 6.2
POSIX AIO – POSIX 準拠 aio_read / aio_write, aio_error, aio_return, …システムコール 通知方法は SIGEV_KEVENT のみ
SIGEV_KEVENT: kqueue(2) と kevent(2) で通知 SIGEV_THREAD 、 SIGEV_SIGNAL は使えない><
Copyright © KLab Inc. All rights reserved.
アジェンダ
非同期 I/O を使う理由 非同期 I/O とは? AIO の実装を紹介 AIO の使い方 落穂ひろい
Copyright © KLab Inc. All rights reserved.
POSIX AIO – スレッド通知
iocb->aio_fildes = …
iocb->aio_buf = …
iocb->aio_nbytes = …
iocb->aio_offset = …
iocb->aio_sigevent.sigev_notify = SIGEV_THREAD;
iocb->aio_sigevent.sigev_notify_function = rd_done;
iocb->aio_sigevent.sigev_value.sival_ptr = iocb;
aio_read(iocb);
/* void rd_done(sigval_t sigval) */
iocb = (struct aiocb *)sigval.sival_ptr;
while ((rc = aio_error(iocb)) == EINPROGRESS);
rc = aio_return(iocb);
char *buf = (void *)iocb->aio_buf;
struct aiocb の初期化struct aiocb の初期化
aiocb を取り出すaiocb を取り出す
データが詰まってる bufデータが詰まってる buf
返り値を得る返り値を得る
エラー状態を確認エラー状態を確認
スレッドを起床して通知スレッドを起床して通知
コールバック関数コールバック関数
自分自身を格納自分自身を格納
非同期処理をリクエスト非同期処理をリクエスト
Copyright © KLab Inc. All rights reserved.
POSIX AIO – スレッド通知/注意点
スレッドセーフではない関数の一覧 http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_09.html#tag_02_09_01
Copyright © KLab Inc. All rights reserved.
POSIX AIO – シグナル通知
iocb->aio_fildes = …
iocb->aio_buf = …
iocb->aio_nbytes = …
iocb->aio_offset = …
iocb->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
iocb->aio_sigevent.sigev_signo = SIGIO_READ;
iocb->aio_sigevent.sigev_value.sival_ptr = iocb;
aio_read(iocb);
/* void rd_done(int signo, siginfo_t *info, void *context) */
iocb = (struct aiocb *)info->si_value.sival_ptr;
while ((rc = aio_error(iocb)) == EINPROGRESS);
rc = aio_return(iocb);
char *buf = (void *)iocb->aio_buf;
struct aiocb の初期化struct aiocb の初期化
aiocb を取り出す☚aiocb を取り出す☚
データが詰まってる bufデータが詰まってる buf
返り値を得る返り値を得る
エラー状態を確認エラー状態を確認
シグナルで通知☚シグナルで通知☚
発生シグナルを指定☚発生シグナルを指定☚
自分自身を格納自分自身を格納
sigemptyset(&sigact_r.sa_mask);
sigact_r.sa_flags = SA_SIGINFO;
sigact_r.sa_sigaction = rd_done;
sigaction(SIGIO_READ, &sigact_r, NULL);
シグナルハンドラシグナルハンドラ
非同期処理をリクエスト非同期処理をリクエスト
Copyright © KLab Inc. All rights reserved.
POSIX AIO – シグナル通知/注意点
シグナルセーフである関数の一覧 http://www.linux.or.jp/JM/html/LDP_man-pag
es/man7/signal.7.html#lbAH
Copyright © KLab Inc. All rights reserved.
libaio
io_queue_init(AIO_MAXIO, &myctx);
struct iocb *ioq[n];
for (i=0; i<=n; i++) {
io_prep_pread(iocb, srcfd, iosize, offset);
io_set_callback(iocb, rd_done);
ioq[i] = iocb;
}
io_submit(myctx, n, ioq);
io_queue_run(myctx);
io_queue_wait(myctx, NULL);
/* void rd_done(io_context_t ctx, struct iocb *iocb, long res,…) */
int iosize = iocb->u.c.nbytes;
char *buf = iocb->u.c.buf;
off_t offset = iocb->u.c.offset;
非同期イベント処理→ CB非同期イベント処理→ CB
データが詰まってる bufデータが詰まってる buf
コンテキストの初期化コンテキストの初期化
iocb のセットアップ (read)iocb のセットアップ (read)
コールバック関数のセットコールバック関数のセット
非同期処理をリクエスト非同期処理をリクエスト
非同期処理の完了を待つ非同期処理の完了を待つ
Copyright © KLab Inc. All rights reserved.
サンプルコードのありか
http://klab.klab.org/trac/general/wiki/aio-copy
Copyright © KLab Inc. All rights reserved.
アジェンダ
非同期 I/O を使う理由 非同期 I/O とは? AIO の実装を紹介 AIO の使い方 落穂ひろい
Copyright © KLab Inc. All rights reserved.
sival_ptr と sigval_ptr
sigval union - /usr/include/sys/signal.h sival_ptr
POSIX, Linux sigval_ptr
FreeBSD, Mac OS X
/* borrow from lighttpd-1.5.0 */
#if (defined(__FreeBSD__) || defined(__DragonFly__))
#define sival_ptr sigval_ptr
#endif
Copyright © KLab Inc. All rights reserved.
AIO を使っているプロダクト
lighttpd-1.5.0 (PRE RELEASE) Linux : libaio (io_submit + io_getevent
s) POSIX : AIO (SIGEV_THREAD) FreeBSD : ×
nginx-0.6.4 (んぎんくす ) Linux : × (たぶん…) FreeBSD : AIO (SIGEV_KEVENT)
io_queue_*を使っていない。
が、実は io_queue_*は io_setup や io_getevents のラッパーにすぎない
io_queue_*を使っていない。
が、実は io_queue_*は io_setup や io_getevents のラッパーにすぎない
Copyright © KLab Inc. All rights reserved.
POSIX AIO で扱えるファイルディスクリプタ
regular file名前付きパイプソケット
なんでもおk
Copyright © KLab Inc. All rights reserved.
libaio で扱えるファイルディスクリプタ
regular file
ソケットはダメ名前付きパイプもダメ
Copyright © KLab Inc. All rights reserved.
では、 lighttpd はどこで libaio を使っているのか?
tmpfs(/dev/shm/) にファイルを作る tmpfs 上のファイルを mmap(2) する 非同期に、
ファイルからデータを read して、 mmap(2) した領域に write する
tmpfs 上のファイルを sendfile(2) でソケットに送る
read(2)+write(2) よりもmmap(2)+sendfile(2) のほうが早い。なぜなら、カーネル内でコピーが行われるから。
read(2)+write(2) よりもmmap(2)+sendfile(2) のほうが早い。なぜなら、カーネル内でコピーが行われるから。
Copyright © KLab Inc. All rights reserved.
レベルトリガとエッジトリガ
epoll(2) デフォルト : レベルトリガ EPOLLET : エッジトリガ
Copyright © KLab Inc. All rights reserved.
レベルトリガとエッジトリガ
レベルトリガ越えている間
はイベントが起こり続ける
エッジトリガ超えた / 下回っ
たときだけイベントが起こる
★★★ ★★★
★ ★
Copyright © KLab Inc. All rights reserved.
レベルトリガとエッジトリガ
レベルトリガ越えている間
はイベントが起こり続ける
エッジトリガ超えた / 下回っ
たときだけイベントが起こる
★★★ ★★★
★ ★
Copyright © KLab Inc. All rights reserved.
Syslets, Threadlets
Syslets, Threadlets (≧2.6.24) http://lwn.net/Articles/219954/ http://www.cuspy.org/blog/2007/07/25/
“Syslets” はカーネル内で小さなプログラムを動作させるための手段であり、システムコールを非同期かつユーザー空間から出ずに実行する方法です。
“Threadlets” はユーザー空間で非同期のコードを実行するメカニズムと同類です。
どちらのケースでも、コードの問い合わせがブロックしない限り同期的に実行されますが、もし何かを待たなければならない場合カーネルはスレッドを生成し ( スペアのスレッドが再利用される場合もある ) 、ユーザー空間でそのスレッドを実行します。このパッチの最初の動機はメンテナンスに大変な手間が掛かる AIO のアプローチを使わずに、完全な非同期 I/O を実装を可能にすることでした。以来、 syslets と threadlets はシステムコールの非同期実行を可能にしただけでなく、より多くのアプリケーションの対応が可能となりました。
“Syslets” はカーネル内で小さなプログラムを動作させるための手段であり、システムコールを非同期かつユーザー空間から出ずに実行する方法です。
“Threadlets” はユーザー空間で非同期のコードを実行するメカニズムと同類です。
どちらのケースでも、コードの問い合わせがブロックしない限り同期的に実行されますが、もし何かを待たなければならない場合カーネルはスレッドを生成し ( スペアのスレッドが再利用される場合もある ) 、ユーザー空間でそのスレッドを実行します。このパッチの最初の動機はメンテナンスに大変な手間が掛かる AIO のアプローチを使わずに、完全な非同期 I/O を実装を可能にすることでした。以来、 syslets と threadlets はシステムコールの非同期実行を可能にしただけでなく、より多くのアプリケーションの対応が可能となりました。
Copyright © KLab Inc. All rights reserved.
参考文献
The C10K problemhttp://www.kegel.com/c10k.htmlhttp://www.hyuki.com/yukiwiki/wiki.cgi?TheC10kProblem
Boost application performance using asynchronous I/O / IBM developerWorkshttp://www-128.ibm.com/developerworks/linux/library/l-async/
Kernel Asynchronous I/O (AIO) Support for Linuxhttp://lse.sourceforge.net/io/aio.html
Copyright © KLab Inc. All rights reserved.
おしまい