「ウェブの歴史は人類の歴史の繰り返し」という観点から色々勉強しています。commentsApache2.4から正式にデフォルトのMPMになったevent_mpmですが、いまいち良さを実感する事ができていませんでした。パフォーマンスも出ないし、これ本当に意味あるの?という人が多かったかもしれません。そこで、マルチプロセッシング周りを真面目にチューニングしてみようと思い、あれこれ試してみると、ある設定値において急にevent_mpmが本気を出し始め、すごいベンチマークスコアを叩きだしたので、それらをまとめようと思います。びっくりしています今回の比較ではキャッシュ等のチューニングは行わず、マルチプロセッシング周りのみのチューニングを行って、純粋なリクエスト処理のアーキテクチャの性能比較を行いました。同時接続数固定の最高処理能力比較これまでは、数十バイトの静的コンテンツを単純に処理する場合、同時接続数を100総接続数10万ぐらいのベンチでNginxよりApacheが性能を出した事を見たことはありませんでした。ブログ等でもあまり見かけた事はありません。それほどNginxの独壇場だったように思います。この分野はNginxの圧勝だろうと思って...いた時期が僕にもありました。実際にevent_mpmの設定を多くのパターンを試して、以下の設定をしたときに、とんでもない性能が発揮されたのです。event_mpmのデフォルトの設定(インストール時)は以下のようになっていますね。0ふむふむ、なんかそれらしい値ですね。Nginxのプロセス周りのデフォルトの設定は以下のようになっています。1024;}この設定で、例えば以下のabコマンドで同時接続数100総接続数10万でベンチをとると以下のようになります。実験環境はいつもと同じです。14708.75はい、これは僕がいつも良く見るApacheとNginxの性能差に見えます。大体、ApacheはNginxの75%程度の性能に落ち着きます。数十バイトの静的コンテンツに対するリクエスト処理はNginxの得意分野だと思っていたので、大体こんなものです。そこで、真面目にevent_mpmのチューニングを行ってみました。幾度となくベンチを試した結果導き出した、静的コンテンツに対する同時接続数100程度に対して最高のパフォーマンスを示すevent_mpmの設定は以下のようになりました。0とてもシンプルですね。デフォルトの設定の見る影もありません。2.66GHzでOS上は4コアに見えていますので、4コアを生かして並列処理時には4スレッドでevent_mpmの特徴である多重化I/Oをするようにしました。コンテキストスイッチを抑える事を意図して、されにMaxRequestWorkersとThreadsPerChildを2にしています。本来MaxRequestWorkersはMaxClientであるため、この設定だと8にする必要がありますが、なぜか、この値をそれぞれ2にするか否かで、性能が20%以上向上する事が分かっています。後述しますが、同時接続数を1000のオーダーにしようとすると、この値はもっとあげないといけませんが、100程度であれば、とにかく1スレッドで同時に処理する数が多くなるように設定した方が、パフォーマンスが大幅に改善する事がわかりました。Nginxに関しては以下のように設定しました。1024;}これは定番の設定ですね。コアの数だけ非同期I/O処理をするプロセスを立ち上げておく事で、より効率よく処理ができます。この設定で、再度同時接続数100総接続数10万でベンチをとりました。17021.03おお、abコマンドのベンチによる静的コンテンツの処理で、ApacheがNginxを上回っているのをはじめてみた気がします。Apacheのevetn_mpmも適切なチューニングによっては、上記のような値が得られる事が分かりました。上記で述べたMaxRequestWorkersとThreadsPerChildの値を例えば4とかに変えると、以下のような値になります。17021.03MaxRequestWorkersとThreadsPerChildの値を1にしてみると以下のような値になります。17021.03MaxRequestWorkersを4、ThreadsPerChildの値を1にしてみると以下のような値になります。17021.03このように、これらの値をWebサーバへのアクセスパターンに合わせてやることで、大きく性能に変化が生じます。event_mpmにおいてはとても大事な値だとわかりました。上記では、Webサーバへのアクセスパターンが例えば同時接続数100ぐらいだと仮定して、それに合わせた最適なチューニングで性能比較を行いました。次に、Nginxやevent_mpmの売りである、同時接続数が1000のオーダーになった時に耐えられるチューニングを行い、性能を評価しました。openfile数の制限を変更します。65536また、httpd-2.4.3/server/mpm/event/event.cのMAX_SERVER_LIMITの値を以下のように変更します。#endifさらに、event_mpmの設定を以下のようにします。0Nginxの設定は以下のようにします。60000;}これで、同時接続数を100から5000に変化させた時のベンチマーク結果は以下のようになります。同時接続数においては、やっぱりNginxはすごいというか、event_mpmは現状千のオーダーでの同時接続数の処理は不十分な所があるという印象を受けました。それでも、元のpreforkやworkerからみると、同時接続数3000とか処理できているのはかなりの進歩にも思えます。Nginxに関しては同時接続数1万どころか、2万でも処理できましたし、それ以降はむしろabの同時接続数の制限値である2万を超えてしまったため計測できませんでした。abコマンド弄ってそれ以上のベンチをとってみたいと思います。event_mpmに負荷を与えていくと、全く反応しなくなることがありました。その時のスレッドをstraceしてみると、以下のようにfutexで処理が全スレッド止まっている事がわかりました。...>このロック周りで刺さってしまって、多重I/Oできなくなるあたりが、まだevent_mpmの不完全な所だと言えるでしょう。ちなみにですが、1スレッドで同時接続処理をするという、Nginxやevent_mpmの特徴を無視して、以下のような力技設定をすれば、余裕でevent_mpmも同時接続数10000とか万のオーダーを処理できるようになります。0これはあまりc10k的ではない、ということで参考情報にして下さい。2万同時接続数とかでも、4265.17request/secぐらいは僕の検証環境でも出ます。nginxだと7368.6くらい出ていました。さんにアドバイスを頂きつつ、再度eventの同時接続数20000あたりをさばけるような設定を検討しました。event_mpmといえども、nginxのようにそれぞれのworkerが複数のリクエストを同時に処理できている、つまりコアの数だけスレッドを用意すれば良いわけではなく、多重スレッド、マルチスレッド、マルチプロセスを組み合わせたようなMPMのアーキテクチャであることが分かってきました。nginxとは違って、きちんとスレッドの数とプロセスの数、及び、同時接続数の数などの組み合わせをきちんと考慮する必要があり、スレッドやプロセスに依存する面があると考えられます。詳しくはマニュアルをご覧下さい。以上を踏まえて、@kfujiedaさんのJAISTでのworker_mpmにおける設定も考慮しつつ、コア4つのメモリ8G環境で、同時接続数を万のオーダーで処理できるような設定を検討した結果、以下のような設定になりました。0この設定で、再度上記で行った同時接続数の変化に対するベンチマークを行うと以下のようになりました。nginxとApacheのeventはかなり良い勝負ができている事がわかります。Apache的にはかなり良い結果なのではないかと思われます。最後に今回はevent_mpmをワークロードに最適化したチューニングを行えば、ある条件下ではNginxよりも早くなる事がわかりました。これは、これまであまり見かけない情報だったので、少し未来を感じる検証結果になったように思えます。追記にも書いた通り、大量の同時接続数を想定したチューニングを行っておけば、nginxと同じような性能を出せる事も分かってきました。ワークロードで細かく設定したい場合はeventを使うという選択肢もでてきたかもしれません。多重I/Oのブロック周りで負荷をかけるとevent_mpmは問題をかかえているように思えます。ここさえクリアになれば、安心してかなり使えるマルチプロセッシングモジュールになるのではないかと思います。いずれにせよ、MaxRequestWorkersとThreadsPerChildのチューニングがevent_mpmを使う上での肝になる事は明らかだと言えるでしょう。この設定方法が、今後のevent_mpmのチューニングの参考になれば良いなと思っています。Nginxの設定に関して勉強したい方はまずは以下の本がよいでしょう。Apacheの設定に関しては以下がおすすめです。Commentコメントを投稿するにはログインしてください。