ISUCON7の予選を突破しました!

ISUCON6からはや一年…

abcang.hatenablog.com

今年も去年と同じメンバー(@mot, @syusui)で「チーム新卒」という名前で参加して、めでたく予選を突破できました!! この記事では自分が主にやったことを書こうと思います。 ちなみに、ソースコードはgitlabにあげてます。 gitlab.com

全体の流れについては@motさんの記事を見てください。 programmermot.hatenablog.com

始まった直後

今回もチームメンバー全員が使い慣れているrubyを使うことにして、まずはstackprofリクエストごとにSQLのログを取れるお手製ツールを仕込んでボトルネックを探しました。

出力結果を見てみると/fetchや/messageにN+1があったり、画像をDBから取得する処理が遅いことに気が付きました。 画像周りは@syusuiくんに任せて、自分は/fetchや/messageのN+1を改善していきました。

アプリケーション側の改善

/fetchのN+1は、チャンネルごとの既読情報の取得未読メッセージ数をカウントするというものでした。 プロファイラを見たところ、既読情報の取得と、既読情報が一つもない場合の未読メッセージ数(そのチャンネルのメッセージの総数)のカウントが多く呼ばれていました。なのでとりあえず既読情報がある場合の未読メッセージ数のカウントはN+1を残したまま、ほかの部分のN+1を改善しました。

あと、謎のsleep 1.0を見て「なんだこのsleepは!?」となりましたが、レギュレーションを読んでいなかった自分は深く考えもせず消してしまいました。(レギュレーションはちゃんと読みましょう)

その後にMySQLでtoo many connectionsが出ると@motさんに言われたので調べていました。 今までの問題をやっててこんなことはなかったよなーと去年の予選の問題と見比べてみたところ、去年の問題ではThread.currentを使用してスレッド内でDBのコネクションを共有していましたが、今年の問題ではリクエストごとにコネクションを張るようになっていたことに気が付きました。過去問大事ですね。

/messageのN+1は単純だったのでサクッと直しました。 また、ベンチ回してると/historyも遅いと表示されたので見てみると、似たようなN+1があったので直してました。

DBの最適化

@syusuiくんが画像をローカルに保存する変更を加えたり、@motさんがnginxの設定を追えて10万点を超えたあたりで、改めてプロファイリングやDBのスロークエリを見ました。 プロファイリングの結果を見ると明らかにクエリの実行に時間がかかっていて、スロークエリの箇所と一致していました。

スロークエリはmessageのテーブルで発生していて、EXPLAINを実行してみるとindexが効いていませんでした。 クエリではchannel_idとidを使っていましたが、idにしかindexがなかったのでchannel_idとidの複合indexを作成しました。 これで20万点近くまで点数が上がりました。

もう一度スロークエリを見てみると、チャンネルのメッセージの総数のカウントに時間がかかっていることに気が付きました。 メッセージはどんどん増えていくので、総数のカウントにかかる時間もどんどん増えていきます。

だいぶ時間も迫っていてredisを入れたくなかったので、カウンターキャッシュを実装することにしました。 新しくmessage_countというテーブルを作成して、メッセージの追加のたびにチャンネルごとにメッセージ数をインクリメントするように変更しました。 また、何度ベンチマークを回しても大丈夫なように/initializeが呼ばれたときにリセットする機能も実装しました。 これで25万点を超え、最終的には268,588点で1日目の2位になることができました!

感想

今回のISUCONの予選の問題が複数台構成だったのでびっくりしましたが、手も足も出なかったISUCON 6本戦での複数台構成のリベンジができてよかったです。 アプリケーション側のボトルネックは事前に練習していたpixiv社内ISUCONと似ていたので、だいぶスムーズに進めれた気がします。

今回は全然レギュレーションを読んでいなくて、あとから/fetchや/messageの得点について知ったので、ちゃんとレギュレーションは読まないとダメだということを再認識しました。もしちゃんと読んでてsleepを残すという考えがあればもう少し点数が伸びていたのかも?

今回のISUCONの個人的な目標は一般枠で予選通過して本戦に出ることだったので、目標が達成できて本当によかったです! 本戦に出たからには何かしらの功績を残せるように頑張りたいです!

iOS10.2環境に入れたtweakまとめ

iOS 10.2の脱獄環境にインストールしたアプリとかのメモです。 動いてないやつとかは随時更新します。

最終更新日: 2017/02/16

  • 2017/05/04
    • CCQuick Pro X for iOS10を追加
  • 2017/05/10
    • TapToOpenを追加
  • 2017/06/17
    • Browser Changer 10を追加
続きを読む

マスコットアプリ文化祭でこのはちゃんとあんずちゃんのアプリを作った話

この記事は、ConoHa Advent Calender 2016の16日目の記事です。

qiita.com

技術的な内容メインじゃないのでQiitaじゃなくてこっちに書きます。 ConoHaにはCoreOSをインストールしていて、DockerでWebアプリをデプロイしてたりします。

マスコットアプリ文化祭とは

企業や団体のイメージキャラクターを使った作品のコンテストです。 作品はアプリに限らず、イラストや動画でもOKな感じになっています。

mascot-apps-contest.azurewebsites.net

このマスコットアプリ文化祭で2014年と2016年はConoHaがスポンサーをしていたため、このはちゃんやあんずちゃんのアプリを作りました。 もちろんどちらのアプリもConoHaで動かしています! それにしてもいつもこのはちゃん負けてますね

f:id:abcang:20161214011055p:plain

mikumo.abcang.net

f:id:abcang:20161214011123p:plain

stamp.mikumo.abcang.net

続きを読む

Tekkaが提供している機能について少し紹介してみます

この記事はTekka Advent Calendar 2016の14日目の記事です。

www.adventar.org

いつもTekkaを見ています。 というのは言い過ぎで全部は見れてないですが、それでも頻繁には見てます。 ROMっている事が多くて、あまり書き込みはしてないです。 その割にはオフライン進捗会(カラオケ会)にそこそこ顔を出している気がします。

さて、今回はTekkaが提供している機能について少しだけ書いてみようと思います。

Tekkaが提供している機能

TekkaはWebブラウザで見ることができます。また、モバイル向けの表示にも対応しています。 現状ではチャンネルがいくつかあり、そこで発言することができます。 ファイルを添付して発言する機能や、手書きで文字や絵を描く機能などがあります。 また、Web Notificationsや棒読みちゃんに対応しているなど、いち早く更新に気付けるようになっています。

Tekkaの目玉機能は、「作品やで」機能でしょうか。 「作品やで」と書かれたチェックボタンにチェックを入れて発言すると、なんと発言の枠が金色(?)に変わり、豪華になります。 創作応援SNSならではの投稿した作品を目立たせる機能ですね。

Tekkaを開発しているゆーひさんによると、まだ未実装機能がたくさんあるようなので、 一般公開される頃にはもう少し機能が増えているかも?

スマホアプリは?

先程モバイル向けの表示にも対応していると言いましたが、 残念ながらスマホアプリは今のところありません。 でも安心してください。 TekkaはAPIを公開しているので、あなたが頑張ればスマホアプリを作ることができるのです!

…はい、本当は自分が作ろうと思ってたのですが、 他の優先度が高いタスクをしてたらもう12月でした。 一応、react nativeを使ってiOSAndroid向けに作って、 reactとelectronでMacWindows向けにクライアントアプリを作りたいなーとざっくりとは考えていました。 なので、いろいろ落ち着いたら作っていきたいと思います。

おわりに

思ったより短い記事になってしまいました。 これはTekkaの機能が少ないのではなく、自分の文章能力がないだけです。

Tekkaにはいろんな物を作っている人たちが集まります。 一般公開されたら、創作が好きな人はぜひのぞいてみてください。 そして、自分のようにROMるのではなく発言していきましょう。

ISUCON本戦に行ってきた

チーム卒業の阿部(ABCanG)です。 めでたく予選を勝ち抜いたのでISUCON本戦に行ってきました。

f:id:abcang:20161101021927j:plain

全体のお話はmot先輩のエントリを見てください。

programmermot.hatenablog.com

時系列で何をしたかとかはsyusuiくんのエントリを見てください。

https://syusui.tumblr.com/post/152682360608/isucon-6-本戦で如何にして人権を失ったか
syusui.tumblr.com

このエントリでは、僕がやったこととか、感想とかを書こうと思います。

当日までにやったこと

画像とか扱う系のが出るのかなーと勝手に予想してて、ISUCON4の本戦の記事とかを眺めたり、 nginxのproxy cacheの設定方法とか軽く見てました。 あまり何もしてないです。

当日

最初、ReactやらDockerやらと言う話を聞いて、マジかってなりました。 日頃からReactとかDockerは軽くは触っていたので、それほど焦りはしませんでしたが、 Docker周りの操作で結構時間を取ってしまいました。

ReactやDockerとはあまり関係のないところで、二つの大きなミスをしてしまいました。 一つは、計測を怠ってしまったことです。 最初のベンチを回した後、計測をしてボトルネックを探すことをせず、 そのまま5台のサーバをどう使うかと話し合ってしまいました。

今思えば、どう分けたら効率がいいかなんて分かるはずもなく、 なんで計測をしなかったのだろうと結構後悔してます。 そんな感じで僕らのチームはReactのサーバを1台とAppのサーバを3台で構築し、 初期実装のスコアより少し低い点で終わってしまいました。 「Appがたくさん呼ばれそうだから多めに配置するほうがいいのでは?」なんて僕が言わなければ運命は変わっていたかもしれない。

もう一つのミスは、5台のサーバを使うタイミングが早すぎたことです。 お昼頃には5台に分散させてましたが、他のチームの話を聞く感じだと終了から3時間前とかにやってる感じでした。 1台でとりあえず高速化して、ボトルネックになる部分を別のサーバに切り分けていくというのが普通なのかーなるほどーって思いました。

自分がやったこと

最初はコードを読んで、アプリの把握をしてました。 Reactのサーバが全部のリクエストを受け取って、APIはそこからプロキシさせてるしマジかってなりました。 アプリの挙動を見ながら、「あー数年前こんな感じの絵チャット作ったなー。でも適当に作ってしまったからあまり活かせる部分なさそうだなー」とか思ってました。

アプリの把握が終わった後は、主にアプリ側をやってました。 アプリにはちらほらN+1問題が仕込まれていたので、 それをせっせと直してました。 Server Sent Eventについてはメンバーのsyusuiくんにやってもらってて、僕はそれ以外の部分という感じです。

N+1問題ですが、先人の方が作ってくださったライブラリを元に自分好みに拡張したものを使って探してました。 このライブラリは、mysql2にモンキーパッチを当てて実行されるSQLと実行時間をログとして出力してくれます。

github.com

当時はこのライブラリはqueryメソッドにしか対応してなくて、本戦のコードではプリペアドステートメントが使われてたので、 しばらくの間なんで何も出力されないんだ?と悩んでました。 原因に気づいてサクッとプリペアドステートメントに(SQL出力部分のみ)対応させて利用しました。 今はプリペアドステートメントが使われている場合も実行時間を取得できるようになってます。

あとはstack-profで遅そうな部分を探したりとかもしてました。

App部分の開発はDockerを使わず、直接手元でRackサーバを立ててやってました。 その方がいろいろ楽だろうと思ってそうしてましたが、後でハマりました。 直接APIを叩いてAPIの動作確認をしていましたが、CSRFトークン付きのリクエストがうまく発行できずに苦しんで結局放置するということをしてしまいました。

N+1問題は減らしたけどスコア上がらないなーって言ってたら終了時間になってました。

まとめと感想

本戦とにかく難しいという印象を持ちました。 特に複数台構成のWebアプリを作ったことがなくて、どうしていけばいいかわかりませんでした。

あとはちゃんと計測しようということですかね、憶測で進めるのはよくないというのが実感できました。 実際、マシンがどれくらいCPU食っているか、もしくは食っていないかを把握できてなくて、 非常によくありませんでした。

スコアを伸ばせなかった原因は、計測を怠って不適切なマシン構成にしてしまったことだと思うので、 今度本戦に出る時はこれを避けれるようになりたいです。

ISUCONをすることで非常に多くのことが学べたので、その点はとても良かったです。 特に、今回の本戦の問題のおかげで複数台構成のコツを少し知れたような気がします。

今後

今年卒業するチーム卒業は、来年はチーム新卒としてリベンジしたいです。 しかしながら、来年は社会人ということで本戦出場のハードルがぐっと上がるので、 本戦に出れるように力をつけていきたいです。

最後に

運営のみなさま本当にありがとうございました!! 非常にいいイベントなので、長く続いてほしいです!

twitterをエゴサしてslackに投稿するやつを作った

最近TLの流れが速くなってきてて、 @付けずに名前が出てきた場合に反応できなくなってきてたので作ってみました。 Dockerでも動くので導入はしやすい(?)と思います。

https://hub.docker.com/r/abcang/slack-twitter-egosa/

github.com

作ったのは1ヶ月ぐらい前ですが、 今回ミュートユーザ、除外キーワード機能を追加しました。 slackに投稿されるツイートはこんな感じに表示されます。

f:id:abcang:20160920231301p:plain

見ての通りそのユーザのアイコンや名前が表示され、 誰の発言内容なのかわかりやすくなっています。 ツイートのリンクも貼ってあるので、すぐにブラウザから見ることもできます。 単に指定した単語が含まれているかどうかを見ているだけなので、 たまに意図しないツイートも引っかかります。

使い方は基本的にgithubのページを見てください。 READMEには書き忘れいましたが、 除外キーワード機能は単語の先頭に-を付けることで有効になります。 検索でよく使われるあれです。

手動エゴサだるい、リアルタイム性が欲しいという方はぜひ使ってみてください。

ISUCON6予選に参加してやったことと反省と感想

ISUCON6予選に学生枠で参加して予選通過しました!!

isucon.net

この記事では主に自分がしたこととか思ったことを書くので、 全体の詳しい話は@pg_mot先輩のエントリを見てください

programmermot.hatenablog.com

当日までにやったこと

@pg_mot先輩がISUCON5の予選のインスタンスを作ってくれてたので、 プロファイラを仕込んで動かしてみたり、 実際にチューニングをしてみたりしてました。

ISUCON5の予選問題はN+1問題がメインで、 必然的にデータベースやSQLのチューニングをすることになったので、 非常にいい勉強になりました。

続きを読む