37
yright © KLab Inc. All rights reserved. 2007 年 8 年 6 年 KLab 年年年年 K 年年年年年年 年年 年年 非非非 I/O 非非 Introduction to Asynchrono us I/O AIO, I/O Multiplexing…

Aio

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Aio

Copyright © KLab Inc. All rights reserved.

2007 年 8 月 6日KLab 株式会社K ラボラトリー廣瀬 正明

非同期 I/O 概説

Introduction to Asynchronous I/OAIO, I/O Multiplexing…

Page 2: Aio

Copyright © KLab Inc. All rights reserved.

今日の目的

非同期 I/O とは何かを知る

非同期 I/O を使うと何がうれしいのかを知る

非同期 I/O を実現する手段(複数)を知る

Page 3: Aio

Copyright © KLab Inc. All rights reserved.

アジェンダ

非同期 I/O を使う理由 非同期 I/O とは? AIO の実装を紹介 AIO の使い方 落穂ひろい

Page 4: Aio

Copyright © KLab Inc. All rights reserved.

アジェンダ

非同期 I/O を使う理由 非同期 I/O とは? AIO の実装を紹介 AIO の使い方 落穂ひろい

Page 5: Aio

Copyright © KLab Inc. All rights reserved.

ネットワークサーバのお仕事を考えてみる

Web サーバとか I/O (ネットワーク I/O 、ディスク I/O )

に着目 リクエストを受ける(ネットワーク read ) ディスクからコンテンツを読む(ディスク re

ad ) レスポンスを返す(ネットワーク write )

Page 6: Aio

Copyright © KLab Inc. All rights reserved.

一般的な I/O の特性

read(2)/write(2) いつでもデータが読める / 書けるとは限らな

い 準備ができるまで戻らない=待たされる

「 I/O ブロッキング」

Page 7: Aio

Copyright © KLab Inc. All rights reserved.

ネットワークサーバ ×I/O

ネットワークサーバ ネットワーク I/O 、ディスク I/O を伴う

I/O ブロッキング I/O で待たされる

単一の処理(リクエスト / レスポンス)を完了するまでに時間がかかる(待たされるので)

単位時間の処理能力が下がる 並行度( concurrent )が下がる

Page 8: Aio

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 戦略について説明しているドキュメント

Page 9: Aio

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

Page 10: Aio

Copyright © KLab Inc. All rights reserved.

アジェンダ

非同期 I/O を使う理由 非同期 I/O とは? AIO の実装を紹介 AIO の使い方 落穂ひろい

Page 11: 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/

Page 12: Aio

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

Page 13: Aio

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独自の実装

Page 14: Aio

Copyright © KLab Inc. All rights reserved.

I/O 多重化 vs AIO

select(2) はブロックする ※タイムアウトは指定可能

通知後に read(2) が必要=コンテキストスイッチ

Page 15: Aio

Copyright © KLab Inc. All rights reserved.

I/O 多重化 vs AIO

ブロックしない=ほかの処理を行えるシグナルかコールバックが非同期に呼ばれる 通知時には既にバッファに入ってる

Page 16: Aio

Copyright © KLab Inc. All rights reserved.

アジェンダ

非同期 I/O を使う理由 非同期 I/O とは? AIO の実装を紹介 AIO の使い方 落穂ひろい

Page 17: 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 より性能は上

Page 18: 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 は使えない><

Page 19: Aio

Copyright © KLab Inc. All rights reserved.

アジェンダ

非同期 I/O を使う理由 非同期 I/O とは? AIO の実装を紹介 AIO の使い方 落穂ひろい

Page 20: 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

返り値を得る返り値を得る

エラー状態を確認エラー状態を確認

スレッドを起床して通知スレッドを起床して通知

コールバック関数コールバック関数

自分自身を格納自分自身を格納

非同期処理をリクエスト非同期処理をリクエスト

Page 21: Aio

Copyright © KLab Inc. All rights reserved.

POSIX AIO – スレッド通知/注意点

スレッドセーフではない関数の一覧 http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_09.html#tag_02_09_01

Page 22: 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_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);

シグナルハンドラシグナルハンドラ

非同期処理をリクエスト非同期処理をリクエスト

Page 23: Aio

Copyright © KLab Inc. All rights reserved.

POSIX AIO – シグナル通知/注意点

シグナルセーフである関数の一覧 http://www.linux.or.jp/JM/html/LDP_man-pag

es/man7/signal.7.html#lbAH

Page 24: Aio

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)

コールバック関数のセットコールバック関数のセット

非同期処理をリクエスト非同期処理をリクエスト

非同期処理の完了を待つ非同期処理の完了を待つ

Page 25: Aio

Copyright © KLab Inc. All rights reserved.

サンプルコードのありか

http://klab.klab.org/trac/general/wiki/aio-copy

Page 26: Aio

Copyright © KLab Inc. All rights reserved.

アジェンダ

非同期 I/O を使う理由 非同期 I/O とは? AIO の実装を紹介 AIO の使い方 落穂ひろい

Page 27: 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

Page 28: Aio

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 のラッパーにすぎない

Page 29: Aio

Copyright © KLab Inc. All rights reserved.

POSIX AIO で扱えるファイルディスクリプタ

regular file名前付きパイプソケット

なんでもおk

Page 30: Aio

Copyright © KLab Inc. All rights reserved.

libaio で扱えるファイルディスクリプタ

regular file

ソケットはダメ名前付きパイプもダメ

Page 31: Aio

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) のほうが早い。なぜなら、カーネル内でコピーが行われるから。

Page 32: Aio

Copyright © KLab Inc. All rights reserved.

レベルトリガとエッジトリガ

epoll(2) デフォルト : レベルトリガ EPOLLET : エッジトリガ

Page 33: Aio

Copyright © KLab Inc. All rights reserved.

レベルトリガとエッジトリガ

レベルトリガ越えている間

はイベントが起こり続ける

エッジトリガ超えた / 下回っ

たときだけイベントが起こる

★★★ ★★★

★ ★

Page 34: Aio

Copyright © KLab Inc. All rights reserved.

レベルトリガとエッジトリガ

レベルトリガ越えている間

はイベントが起こり続ける

エッジトリガ超えた / 下回っ

たときだけイベントが起こる

★★★ ★★★

★ ★

Page 35: Aio

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 はシステムコールの非同期実行を可能にしただけでなく、より多くのアプリケーションの対応が可能となりました。

Page 36: Aio

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

Page 37: Aio

Copyright © KLab Inc. All rights reserved.

おしまい