さて、勇者を育てろですが、、、
このプログラムは仕事の合間に作っている為にリファクタリング等をいっさい行ってませんでした。
フィーリングで作っていつつ、Railsがカバーしてくれているためそこそこ動くという状況でした。
しかし、先週あたりにリリースしたパーティー機能によって戦闘の計算ロジックが大幅に変更されてフィーリングプログラムでは駄目になってしまいました・・・。
どうなったかというと・・・
ロードアベレージが1を超える
という事が発生してしまいました。
ピーク時は絶えず1~2を保つようになってしまい、これはそろそろプログラムに
てこを入れる必要がありました。
で、ロードアベレージって何かというと実行待ちのプロセス数を表す単位になります。
単純に考えると1より低ければそのサーバーは自分の仕事をしている状態になります。しかし、1を超えると一つのCPUでは処理が出来ない状況になります。
瞬発的に1を超える事はほとんど問題になりませんが定期的に1を超えるという事は、どんどん仕事がたまって行く事を意味します。(実際はそんなに単純ではないのですが・・・。)
なので、フィーリングプログラムをリファクタリングしました。
調べてくると出て来たのが以下。
・SQLの重複を押さえる
同じSQLが幾つも流れてる箇所がとても多い。Railsでは同じSelect文が流れている場合はキャッシュを返してくれる。しかし、Update文となると別。
僕のプログラムでは個々のモジュール毎に処理をさせていて、そのモジュール内で処理を完結させるため同じモデルを扱う場合にはあちらこちらでUpdate文が走ってしまっていたのです。
・SQLの発行回数を押さえる
一つ一つのデータを取るパターン。例えば勇者のデータを3つ取得するときは、3回SQLを発行させるのではなくIN句を使って一度のSQLで取得する。こんなの基本的な事だけど、コントローラーをビューにロジックが散らばってしまうと意外と起こる。
また、あまり変動しない値(例えば掲示板のカウント)とかは5分毎に全データを取得してキャッシュに格納させるという事を行った。
今回はMysqlを使用しているためマルチプルINSERT(バルクインサート)が使えるため、Insert文の発行回数も極力抑えた。(ここで難しかったのはhas_manyとバルクインサートを両方使う時だ。※詳細については需要がありそうだったら書きます。)
これによって、SQLの発行回数を大幅に下げました。
・エラー処理を適切なものにする。
勇者を育てろでは、とにかく手を抜いているため・・・(苦笑
エラー時の処理はサーバー内部でエラーを発生させて、クライアントには何もデータを返さなかった。しかし、エラーが発生するたびにExceptionを発生させるのは非常にコストがもったいなかったのでエラー処理を適切に行うようにしました。
僕の場合はロードアベレージは高くてもCPU使用率はそこまで高くなかったので、とにかくSQLを減らしてIOを減らせば良いためこのような対応をしました。
・・・が、ここに書いている以上に大変な作業でした。
で、これによって
ロードアベレージは0.3前後
に落ち着きました。
何にしても、今のユーザー数でこの状態はまずかったので僕としては必死に直しました。
そんな勇者を育てろは
こちら
です。
是非、効果のほどを感じてください・・・って分からないだろうな。。。
P.S.
あと、どさくさにまぎれてパーティメンバーを自分のいる場所に呼び寄せる召還魔法を実装しました。
手に入れるのはかなりきついですが、是非とってください!
(ちなみに、僕は「ジョウ」という名前で冒険していますのでであったら声をかけてください。)
| このブログのURL
|この記事のURL