Hatena::ブログ(Diary)

kazuhoのメモ置き場

2008-05-21

Q4M - とりあえず pwrite を複数スレッドから呼ぶようにしてみた

とりあえず pwrite を複数スレッドから呼ぶようにしてみた。でもってベンチとろうとしたら perl のテストコードじゃサチってどうしようもなくなっていたので C で書いた。

$ MESSAGES=400000 CONCURRENCY=40 DBI='dbi:mysql:test;mysql_socket=/tmp/mysql51.sock' t/05-multireader.t 
1..4
ok 1
ok 2
ok 3
ok 4


Multireader benchmark result:
    Number of messages: 400000
    Number of readers:  40
    Elapsed:            20.282 seconds
    Throughput:         19721.561 mess./sec.

その間の top はこんな感じ。並走度 2.5 あたりが現在の上限らしい (クライアント数を 40 から 80 に変更してもアイドルが発生する) 。次はやっぱ mmap なんでしょうなぁ。

top - 12:20:02 up 40 days, 19:49,  3 users,  load average: 5.85, 2.64, 1.25
Tasks: 192 total,   4 running, 188 sleeping,   0 stopped,   0 zombie
Cpu(s): 44.4%us, 32.6%sy,  0.0%ni, 20.5%id,  2.0%wa,  0.0%hi,  0.5%si,  0.0%st
Mem:  32967696k total, 32433632k used,   534064k free,   458044k buffers
Swap: 10485752k total,        0k used, 10485752k free, 27667516k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND            
17786 kazuho    18   0  369m  27m 4960 S  259  0.1   7:58.66 mysqld             
21515 kazuho    15   0 19240 1504 1168 S    2  0.0   0:00.16 05-multireader-    
21536 kazuho    15   0 19244 1504 1168 S    2  0.0   0:00.14 05-multireader-    
21538 kazuho    15   0 19244 1508 1168 S    2  0.0   0:00.17 05-multireader-    
21586 kazuho    15   0 19240 1504 1168 S    2  0.0   0:00.17 05-multireader-    
21513 kazuho    15   0 19244 1504 1168 S    1  0.0   0:00.15 05-multireader-    
21514 kazuho    15   0 19244 1508 1168 S    1  0.0   0:00.13 05-multireader-    
21516 kazuho    15   0 19244 1508 1168 R    1  0.0   0:00.15 05-multireader-    
21517 kazuho    15   0 19244 1504 1168 S    1  0.0   0:00.15 05-multireader-    
21520 kazuho    15   0 19244 1508 1168 S    1  0.0   0:00.16 05-multireader-    
21530 kazuho    15   0 19240 1504 1168 S    1  0.0   0:00.15 05-multireader-    
21531 kazuho    15   0 19240 1504 1168 S    1  0.0   0:00.15 05-multireader-    
21539 kazuho    15   0 19244 1500 1168 S    1  0.0   0:00.15 05-multireader-    
21543 kazuho    15   0 19240 1504 1168 S    1  0.0   0:00.17 05-multireader-    
21544 kazuho    15   0 19240 1504 1168 S    1  0.0   0:00.17 05-multireader-    
21549 kazuho    15   0 19244 1504 1168 R    1  0.0   0:00.15 05-multireader-    
21550 kazuho    15   0 19240 1504 1168 S    1  0.0   0:00.15 05-multireader-    
21552 kazuho    15   0 19240 1504 1168 S    1  0.0   0:00.16 05-multireader-    
21553 kazuho    15   0 19244 1508 1168 S    1  0.0   0:00.16 05-multireader-    
21563 kazuho    15   0 19240 1500 1168 S    1  0.0   0:00.14 05-multireader-    
21565 kazuho    15   0 19244 1504 1168 S    1  0.0   0:00.16 05-multireader-    
21571 kazuho    15   0 19240 1504 1168 S    1  0.0   0:00.16 05-multireader-    
21579 kazuho    15   0 19244 1504 1168 S    1  0.0   0:00.14 05-multireader-    
21580 kazuho    15   0 19240 1504 1168 S    1  0.0   0:00.15 05-multireader-    
21581 kazuho    15   0 19240 1504 1168 S    1  0.0   0:00.15 05-multireader-    
21588 kazuho    15   0 19240 1504 1168 S    1  0.0   0:00.16 05-multireader-    
21589 kazuho    15   0 19240 1500 1168 S    1  0.0   0:00.14 05-multireader-    

13:07追記: むー、どうも pwrite の直列化が律速じゃなかったみたい。結局 --with-mt-pwrite=no してもほとんど変わらない速度が出る。ちなみに --with-sync=no して fsync やめると 30,000 transaction/sec. 近い値が出る。

nishidakeisukenishidakeisuke 2008/05/21 13:32 どーも、ご無沙汰してます。楽しそうなことやってますね(笑)
クライアントをなくして、プログラム内部でpwrite&fsyncし続けたときの限界性能はどのくらいになるんでしょうか?つまり、ボトルネックはI/Oなのかどうかという。
マルチプロセッサはいろんなところがボトルネックになるみたいで面白いですね。
http://d.hatena.ne.jp/nishidakeisuke/20080517/p3

kazuhookukazuhooku 2008/05/21 16:29 ご無沙汰です。ご活躍、拝読させていただいています。

マルチプロセッサはおもしろいですね。英語ブログ強化キャンペーン中ということで、内部性能についてはそちらに考察を書かせていただきました。
http://labs.cybozu.co.jp/blog/kazuhoatwork/2008/05/maximum_peformance_of_mysql_an.php

結論としては、やはり、fsync 以外の I/O 関連のシステムコールはボトルネックではなく、mutex による直列化をいかに避けるか、という話になるのかなと思いました。

nishidakeisukenishidakeisuke 2008/05/22 00:37 ふむー。仮に頑張って手を入れても、性能が何倍にもなるようなものではなさそうですね。だとしたら深入りしない方が賢明?

でもアイドル時間があるのはどういう理屈だろう。I/Oの待ち時間であればwaが増加しますよね?グループコミットによって一つのスレッドだけが書き込みを行なっていて(wa増加)、それが完了するまでは他のスレッドは待っている(id増加)ということでしょうか?

ディスクとsyncするのであれば、原理的にそれ以上の改善は難しい気がする・・(ディスクドライブ&ファイルを分けるとかして、syncそのものを並列化するしか)

逆にsyncを諦めるのであれば、全ての処理をメモリ上で完結させて、ときどき別スレッドで「ロック→メモリコピー→アンロック→まとめてディスクに書き込み」とか?

nishidakeisukenishidakeisuke 2008/05/22 01:21 あ。全部オンメモリでやれるほどデータが小さいとも限りませんね・・。するとやっぱりmmapになるんだろうか。

でも、mmapしたメモリって読み書きすると実メモリを消費しますよね。もしもメモリが足りなくなると、スワップと同じ原理で、変更のあった部分が自動的にファイルに書き出されるんでしょうか?その場合、書き込みはどのスレッドで行なわれるんだろう・・

クライアントのスレッドがI/Oによってブロックしてしまうのを避けるには、やはりI/Oだけスレッドを分離させて、そいつに非同期な書き込みや先読みをやらせるのもありですね。今度ブログネタに取り上げてみようかな(笑)

kazuhookukazuhooku 2008/05/22 09:00 アイドル時間と最適化のメリットについてですが、このベンチマークは、どちらかというとキューの消費速度を測定しており、上記追記の設定 --with-sync=no --with-mt-pwrite=yes においては、キューの消費においてグループコミット風の処理は行われない感じです。ただ、その場合でも idle が発生します。原因については、現状、読み込みを直列化してキャッシュしているので、そこ (あるいはその他 mutex lock がかかる部分) で待ちが発生しているのではないかとかんがえています。

で、解決方法としては、読込キャッシュを廃止して各スレッドから直接 pread を呼ぶようにするというのが一案になりますが、それだと並走性は上がっても 2 core 以下の環境では速度が低下するでしょうから、やりたくないなと思っています。となると、mmap がいいのかなぁ、と。キャッシュ消費の書き込みも 1 バイトの pwrite なのですが、mmap を使っていればこのオーバーヘッドも小さくなりますし。

パフォーマンスチューニングの上界については、現在の環境ではどうがんばっても2倍程度にしかならなない、というのはそのとおりなのですが、書いたとおり並走性の問題があるので、例えば 8 core の環境ではもっと大きな効果が望めるということになるのだろう、と思います。

kazuhookukazuhooku 2008/05/22 09:24 で、この事情は --with-sync=fdatasync (デフォルト) の場合でも変わらないと思います。つまり、f(data)sync のオーバーヘッドについてはグループコミットによってある程度隠蔽できているが、並走性の悪さにともなうアイドルが発生している、と。

mmap された領域については、最近の OS の実装だとファイルのバッファキャッシュと同様の扱いを受けるんじゃなかったでしたっけ? このへん詳しくないのですが、あまり心配していない感じです。アクセスパターンについては madvise でどの程度うまくいくのか、ということになるのでしょうね...

ただ、今回の最適化は MySQL AB の Brian Aker に「もっと速くできるよね」と言われたことが端緒なので、目標値がないのがなんだかな、という気はしています (ぉ

nishidakeisukenishidakeisuke 2008/05/22 20:46 なるほど。mmapって実際のところどれくらい速いのかという感覚がわからないので、使ったことがないんですよね。システムコールがなくなるから速いんだろうか。
続報、楽しみにしています(笑)

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/kazuhooku/20080521/1211340322