CyberAgent 2days サーバーサイド向け 開発型インターンシップ ONLINE に参加してきたログ

こんにちは とさです

6/7~6/8 で CyberAgent の 2day サーバーサイド向け 開発型インターンシップに参加していました!

まず初めに結果としては全体のちょうど半分の 10 位で終了しました。 なので、参加者の丁度中央だった自分がどのようにチューニングに挑戦していたのかを記録していきたいと思います。

実施前にやったこと

golang のプロファイリングツールである pprof と nginx の計測ツールの alp について調査とテストを行っていました。また isucon7 の予選の解説 pdf が販売されていたので購入してパラパラとめくって学習していました。

ただ、インターンシップの面接の際も nginx(エンジンエックス)について知っていますか?と聞かれた時点では nginx(ネギシン)と読むのだと勘違いしていたくらい知識がありませんでした。

開始 〜 一日目前半

初期点は 700 くらい、まずは github にファイルをあげてローカルで開発しようとしたのですが、ファイル権限等の調節がうまくいかず、いじるファイルが少ないことから vim と scp によるファイル転送で開発していく方針に変更しました。(効率悪かったのでファイル権限をちゃんと設定するか vim が触れるなら直接変更した方が良いです)

# scpコマンド
scp file_name hogehoge@hostname:/dirctory/

1 日目 後半

途中でランチタイムが入り、周りの学生エンジニアさんと話せて息抜きをしつつ午後へ。

相変わらず github の設定で四苦八苦しつつ、そもそも golang のサーバーの再起動の仕方がわからず...といろいろわからないことだらけだったので(だめだめ)ぐぐったりメンターさんに聞きながら作業を進めていました。

# システムの再起動
# ここら辺はsystemdで管理されています!!
sudo systemctl restart hogehoge

またここら辺で nginx.conf を操作の慣れていない vim でデータを吹き飛ばしたりしていました。(再度ファイルをもらいました、、お手数おかけします)(vim は:wq で保存されるので無意識に打ってしまいました w 皆さんも気をつけましょう)

alp を使用した解析を行いたかったのですがうまくいかず、メンターさんに聞いたところ nginx.conf ではなく別の場所でも設定がありそちらの server ディレクティブに記入しなければならないらしく、、、時間を取られてしまいましたがようやく解析ができるようになりました。

初日解説〜終了

解析ができるようになった時点で初日解説の時間。 index の貼り方一つでスピードが全然変わることに驚きでした。 slow クエリの調べ方や実際に index が使用されているかの見方を解説してもらいました。

解説を参考に query を貼って 700 -> 1300 にスコアを上げることができました!(:ドヤ

その後、は slow クエリを探して index を貼ったら高速化できそうなところに貼って 1300 -> 1500 にスコアを伸ばして初日は終了しました。

また、この日の夜に使用言語の指定処理をやり忘れていたみたいで php -> golang に設定し直しました。

※ましさんに教えてもらいました、ありがとうございます!

2 日目 前半

二日目は alp の解析結果をもとにログイン後の初期ページの動作が遅いことがわかってのでそこを改善していくことに、どうみてもアカウントのアイコン画像を表示する処理が重たい(base64 で配信している)ことがわかったので直接静的ファイルを参照するように変更しました。

    location / {
        try_files $uri "${uri}.png" @backend;
    }

具体的には/photo/{id}を叩くと/photo/{id}.png に直接参照するように nginx の try_files を変更して改善すると、ホームページの画像がすごく早く表示するようになりました!

これはもしかしたら 6000 点を超えてしまうのではないか?トップあざす!と期待しながらベンチマークをすると得点が全く変わっていないという悲劇に。。。

ベンチマークが何を参考に得点を決めているのかをしっかり確認すべきだなと終わってみてから反省しています。

切り替えてスロークエリログを調査することに

mysql> set global slow_query_log = 1;
mysql> set global long_query_time = 0;
mysql> set global slow_query_log_file = "/tmp/slow.log";
bashに戻って
sudo pt-query-digest /tmp/slow.log > /tmp/digest.txt

解析をしてみるとおすすめ記事を表示する sql が遅いことを確認!ここを改善してみようといろいろ頑張りましたがどうやら sql の書き方自体に悪いところが見当たらず、、ちょっと行き詰まり感がありました。

2 日目 後半

sql が遅いのならば予めその値を保持できるのであれば保持しておいて sql を実行せずにその値を返せばいいのでは?と思い立ち global 変数に値を保持して、その値に関連する動作が起こったら flag を立ち上げて再度取得するように変更してみました。

// 焦りすぎてスペル間違っているとか汚いとかはご愛敬
var (
	cachePopularArticle []PopularArticle
	chachOnlineUser     []int
	onlineflag     bool = false
	popflag        bool = false
	chachearticles int
	articlesflag   bool = false
	tagsCount      int
	tagsCountFlag  bool = false
)

この作業をしている間に時間は経ち score は 1500 -> 1700 に改善しました! (ただ、不具合が生じることがありベンチマークが FAIL することも多かったです。)

※ 競技終了までこのれがインメモリ戦略だと思っていました。 ※ 授業でメモリを習ったのに...

結果

最終結果は 1723 点が最大値で 20 人中ドンピシャで 10 位でした。2000 点いきたかったですが、ガッツリ二日間集中して開発に打ち込めてとても楽しかったです!アドレナリン出まくりで初日が終了した時点で両腕が筋肉痛になる程、プログラミングが楽しいものだと再度実感しました。

競技終了後、解説があり。

  • Mysql インデックスチューイング
  • インメモリキャッシュ、N+1 除去
  • golang 特有のチューニング

の三つのステップで 7500 点を超えた事例の説明を受けました。redis によるインメモリキャッシュのやり方や、golang の template エンジンが reflact によって遅くなっている部分の解消のやり方など、いろいろな観点で改善法を学べてめちゃくちゃ面白かったです!

また、nginx を外して golang の 80 番を直接 Listen するなど、これを使わなくてはいけない!っていう常識にとらわれて本質が見えていないと改善できない部分もありました。

当たり前ですが「知らない」技術はもちろん使うことができないので、こうした機会にいろいろな技術を「知る」ことができるのがとてもありがたいです。次回は是非今回学んだことを「使える」まで磨いて挑戦したいと思っています。

また、競技終了後 CyberAgent さんの LT や社員懇談会もありいろいろな裏話が聞けてとても楽しかったです!社内の雰囲気がとてもよく伝わってきました。

個人的に社内インフラのサーバーの画像をみたときにめちゃくちゃかっこいい!ここで寝転がりたい! って興奮したのが印象に残っています。

次は ISUCON にも出場する予定なのでのでもっと学習して予選突破目指して頑張りたいと思います!


競技中に参考にしたブログ

【Golang】gob で変数をファイルに保存する

【MySQL】遅い select 文の原因を調査する【explain の読み方】

nginx の try_files わかりにくすぎ問題

ISUCON 史上初の学生チーム優勝! 勝利のカギは「チームワーク」と「失敗からの学び

LT でこの記事に載っていた本物の人が出てきて驚きました w


他の参加者のブログ

技術的な視点からとても勉強になりますので是非!

さんぽしさん

kiyo さん

ましさん

hpp さん

やよいさん

Santos Kota さん

AkkyOrz さん

Home...