KLabGames Tech Blog

KLabは、多くのスマートフォン向けゲームを開発・提供しています。 スマートフォン向けゲームの開発と運用は、Webソーシャルゲームと比べて格段に複雑で、またコンシューマゲーム開発とも異なったノウハウが求められる領域もあります。 このブログでは、KLabのゲーム開発・運用の中で培われた様々な技術や挑戦とそのノウハウについて、広く紹介していきます。

@hasi_t です。 http://klabgames.tech.blog.jp.klab.com/archives/1072352628.html の続きです。

hasi_tがやったことの時系列

  • 10:00-11:30 問題を把握する
  • 11:30-12:30 nginxをインストールする
  • 12:30-13:00 昼食
  • 13:00-14:40 getEventsとgetEventを修正する : getEventsからgetEventを呼ばないようにし、SELECT * FROM sheetsを1回にし、SELECT * FROM reservationsのN+1問題を対処
  • 14:40-15:30 /admin/api/reports/sales, /admin/api/reports/events/:id/sales修正 : order by reserved_at asc を削り、数値比較でソートするように修正、getEvent呼出を削除
  • 15:30-16:00 Failしているのをなんとかしようとする
  • 16:00-16:20 SQLのロックを外して、goでロックを取るように修正
  • 16:20-17:00 /api/users/:id修正 : getEventの結果の使いまわしを実装、getEventNoDetail・getEventNoSheetsを作成
  • 17:00-17:10 reservations.user_idにINDEXを張る
  • 17:10-17:40 オンメモリキャッシュのつなぎ込み
  • 17:40-18:00 おしゃべり

目立った点

nginx化

sudo yum install nginx で適当にインストールして実行ユーザを変えたのですが、
nginxのテンポラリディレクトリの権限を付けておらず、
/admin/api/reports/events/:id/sales/admin/api/reports/sales のようにレスポンスデータが大きい場合のみエラーが発生する、
という問題を起こしてしまいました。

nginxのエラーログを見たら Permission denied が出まくってるのですぐ気づきそうなものだったのですが、
全く見ておらず、それに気づかず16時までfailし続けていました。
動作が遅いからfailしているのでは?とか言っていろいろ修正していたのですが、
ブラウザでダウンロードしようとするとネットワークエラーになり、
ログを見たらエラーが出ているという状況でした。
ベンチマーカのログを見てちゃんと確認したらすぐ分かったことで、深く反省していますorz

野蛮なロック

予約/キャンセルAPI全体のロック を取りました。
これによってSQLのFOR UPDATEは不要になります。
常日頃から並列処理やロックは扱えないと公言して憚らないので、自分としては普段どおりです。(自慢できることではない)
結果的にはダブルブッキングやデッドロックといった様々な問題が未然に防げたようなので良かったです。

感想

反省点は多いですが、結果的には良かったので良かったです。
準備してもらったレポートツールはとても優秀で楽しくチューニングできました。

昨年作問を担当したので運営側の大変さはとてもわかるのですが、 特にベンチマーカがどんな実装だったのかと気になっています。
これを作るのはめちゃくちゃ大変だったのでは…

本選を楽しみにしています!

こんにちは, @mecha_g3 です.

ISUCON8というサーバチューニングコンテストで予選に参加したので, 自分のやった事を書きます.
予選1日目の4位, 全体10位という結果で無事予選通過することができました.

リポジトリとベンチマークの結果を貼っておきます. ベンチマークレポートは最後ログを切ってしまった都合上, 最終の一つ前のベンチマークのものです.

チーム

ISUCON4, ISUCON5 で予選落ちした DiamondPrincess (@hasi_t, @mecha_g3, @pandax381) です.
ISUCON6 は本気で勝ちに行って僕は別チームに. ISUCON7 は問題作ってました.
今年はゆるふわ参加が良いな〜と言いながら, 初期 DiamondPrincess メンバでの参加になりました.

事前練習の予定が合わないのでぶっつけ本番でいくことになり, 予選通過はほぼ無理な雰囲気だったのですが, うっかり予選通過したら考えよう!OpenRestyつかってNginxLuaで遊びたい!とか話してました.

予選3日前

社内のもう1チームが練習しているチャットで Pixiv 社内ISUCON2016 のCentOS版イメージが作成されていたので共有してもらいました.

急にやる気が出てきたのでそのイメージを使って開発環境を整え, 昔作ったプロファイリング系のツールの動かし方を確認し, 軽くチューニングする練習をしたり, スタートダッシュシート(開始直後TODOリスト)を作りました.

予選

開始直前に会社の会議室に集合しコンテスト開始.

以下, 僕のやったことを時系列で

  • 10:00-12:00 ポータルに対してエンキューとスコア取得を行うスクリプトの作成. Puppeteerを作業環境上で動かすのに苦労する.
  • 12:00-13:00 作業環境上で開発できるようにする. デプロイやログ取得周りのスクリプトの整備を手伝い, 開発環境が整備されていく.
  • 13:00-14:00 MariaDB -> MySQLに置き換え. プロファイラの有効化, レポートが見れるようになる.
  • 14:00-17:30 User, Sheet, Reservation, Event, SheetSlice, ReservedTimes, ReservedUserID のオンメモリキャッシュ作成・適用・バグ修正.
  • 17:30-17:40 再起動試験しますと言いながら開発環境を再起動したり, MySQLにつながらなかったら1秒スリープして再接続 しない みたいなコードを書く.
  • 17:40-17:50 pprofを有効化するフラグをfalseにする(ただしそのフラグは使われていない).
  • 17:50-17:55 お祈り

目立った点

コマンドからエンキュー

Puppeteerでポータルに対してエンキューとスコア取得を行うスクリプトを書きました. コマンドでエンキューやスコア取得ができるようになりました.
開発環境上で動かすのに苦労して2時間も使ってしまいました.

nginx化

h2o速そうだけど全く使ったことがなかったので nginx を使うことにしました. これは @hasi_t にお任せしていました.
パーミッションの問題で一部のレスポンスが返せずハマってしまい, 16時までベンチが通りませんでした.

予約とキャンセル排他制御

@hasi_tにより予約/キャンセルAPI全体にMutexでロックを取るロックな実装がなされていました.
他チームはトランザクション絡みでランダムなfailが起こっていたり, スコアが安定しないという話でしたが, これのおかげかうちのチームは変なfailはありませんでした.

MySQL化

myprofilerがmariaDBで動かなかったのでMySQLを使うことにしました.
最初MySQLが起動せず困ったのですが, @pandax381 が my.cnf がmariaDBのものを参照していた事が原因とすぐ特定してくれて助かりました.

オンメモリ化

ベンチマークが通っていない間から作り始め, 最終的に User, Sheet, Reservation, Event, ReservedTimes, ReservedUserID のオンメモリストアができました. Sheet, Reservation, Event あたりはメモリに載せただけで使ってないです. 関数を作って呼び出すの忘れるみたいなことを何度もしてしまいました.

スコアの遷移

16:00過ぎに nginx 後初めてベンチが通り, 6000点台でした. そこから @hasi_t とペアプロしながらオンメモリキャッシュを適用していきました. 改善を入れるたびにぐんぐんスコアが伸びていきました.

17:30あたりで再起動試験をしてみたらdbに接続できずにアプリが立ち上がって来ない問題が起きましたが, @pandax381 が一瞬で原因を見つけてくれてシュッと直してくれました.

次 35,000点 超えたら終わりにましょう, と言いながらログを切ったり再起動したりしてベンチかけると 42,181点 が出たのでここで終わりにしました.

レポート系のAPIのチューニングが手付かずに終わってしまったので, 予選通過できるか不安なスコアでした.

感想

今年はゆるふわ参加とか言っていましたが, いざチューニングし始めると楽しいISUCONを思い出してきて夢中になって, 結果的に予選突破してしまいました.
全くチーム練習していなかった割には 3人とも活躍できました. お互いの得意分野が大体分かっているのと, 準備してきたレポートツールなどが優秀でチューニングポイントを迷わなかったのが勝因だと思います.
本戦の席を奪ったからには, ちゃんと練習して挑みたいと思います!

昨年作問を担当したので運営側の大変さはとてもわかるのですが, このクオリティの問題と安定したインフラを準備してくるの, すごすぎると思いました.
ポータルサイトも超カッコよくなっていて, 昨年導入した負荷レベルの概念とかベンチマーカーからのメッセージとかが継承されていて嬉しくなりました. ベンチマーカー作るの本当に大変なんですよね...
競技中はボリューム大きすぎ, 難易度高過ぎと思いましたが, 終わってみるとボリュームと難易度のバランスの良い良問でした. 本戦で裏話が聞けるのが今から楽しみです.

こんにちは、s_naritada です。
6/13にAiming × KLab コラボMeetup!を開催しました。
今回、登壇発表させていただきましたので発表時の補足解説を少ししたいと思います。

Aiming × KLab コラボMeetup!について

株式会社AimingとKLab株式会社でコラボしてスマホ向けのゲーム開発について
両社からそれぞれ2名のエンジニアが登壇して「ゲーム演出」をテーマに発表を行う勉強会です。
立食しながら発表を聞く形式をとっており、気軽な雰囲気で聞いていただけました。

本稿は、当日発表した内容の補足解説となっております。
最初に発表で使用した以下のスライドを御覧ください。

出現演出の補足

公開スライドでは、静止画になっているので再掲します。

digital_fix_02
digital_fix_06

上記の出現シェーダーを作りました。
以下は、出現演出のシェーダーコードになります。

float4 textureColor = tex2D(_MainTex, float2(input.tex.xy));

// sinは-1~1で帰ってくるので0-1に正規化している
float mask_value = sin(input.screen_position_y * 200) * 0.5 + 0.5;

// テクスチャ色とカラーパターンを合わせる
float col = textureColor * input.color;
col.a = min(step(mask_value, _CutOff), col.a);

col.rgb = lerp(_Color.rgb, col.rgb, min(1, _CutOff));

return col;

マスクするテクスチャは以下のコードで自動生成しています。
画面からの座標を取得できるのでそれをsin値で変換して作っております。

// sinは-1~1で帰ってくるので0-1に正規化している
float mask_value = sin(input.screen_position_y * 200) * 0.5 + 0.5;

画像のような見た目になります。
_CutOffで設定した0-1の値が来ると値に応じて画像がマスクされていきます

sin_pattern_01

input.screen_position_yは、画面のY座標になっており
以下のコードで事前に頂点シェーダで算出して入れておきます。

float4 screen_pos = ComputeScreenPos(output.pos);
output.screen_position_y = screen_pos.y / screen_pos.w;

次に以下のコードで設定した閾値以下はアルファ値を0にするようにしています。

col.a = min(step(mask_value, _CutOff), col.a);

そして最後に閾値に応じて指定した色味を重ねる処理を入れてます。

col.rgb = lerp(_Color.rgb, col.rgb, min(1, _CutOff));

以上、出現シェーダーの補足説明でした。

スライド画像の補足

最後に掲載したスライドで静止画になってしまった画像を載せておきます。

ページ番号 画像
11 digital_fix_01
12 digital_fix_08digital_fix_07
13 digital_fix_03
14 digital_fix_02digital_fix_06

あとがき

こうした外部の勉強会での発表は初めてでしたが多くの人に聞いてもらうことができました。
イベントを用意していただいた運営の皆様、参加いただいた皆様、
版権作品を載せることを許可頂いた版元様、ありがとうございました。
これからも有志として発表活動を続けていきたいと思います。

©久保帯人/集英社・テレビ東京・dentsu・ぴえろ ©KLabGames

↑このページのトップヘ