りにゅうしょく

競技プログラミング 日常

新卒エンジニアのISUCON参加記(ISUCON12)

スギノキです。kakiraちゃん(kakira9618)、かいとさん(tran0826)と一緒に「kakipippi」というチームでISUCON12に参加しました。結果は振るいませんでしたが、とても勉強になった8時間でした。
忘れないうちに参加記を残して次に向けてのモチベーションを高めようね、という話になり3万年ぶりに宝塚以外の内容でブログを書くことに……(このブログは宝塚歌劇遠征の道中新幹線で書かれています)
この記事に特にためになることはありません 技術ブログではありませんのでご容赦ください こんな軽いノリで参加していいんやな~くらいに見てください 嘘を書いている部分があればご指摘くださるとうれしいです

チーム決め~事前練習のこと

いとさんは会社の先輩で、勉強したいからISUCON出たいな~と言ったらチームを組むことを快諾してくれました。ただ社内に共通の知り合いがいるわけではないため、残り1人が見つけられず、Twitterで募集を掛けたところkakiraちゃんがリプライをくれました。kakiraちゃんは競プロキャンプで少しお話したくらいでしたが、見るからに優しそうオーラがあったのでよっしゃこの3人で行くぜ~~!ということになりました。この時点で6月上旬と、予選まで1か月ほど猶予がありました。


事前練習(Discordで集まってワイワイ話すこと)は大体週1の頻度で本番までに5回行いました。と言っても、私がほんっっっっとうにWebド素人で何も分からない状態だったため、最初の3回は「kakiraちゃん先生によるWebのしくみ説明会」みたいな感じで座学を教えてもらっていました。


ISUCONはいくつかの言語で参考実装があるものの、どれもほとんどさわったことがなかった*1ため、「はやそう」「過去の知見が沢山ネットに落ちてそう」くらいの理由でGoに決めました。メルカリがSlackで公開している Gopher道場 を見ながら文法を勉強しました(と言いつつ、新卒研修も同時期にあったため全然勉強できていませんでした……)。


ISUCONの過去問にチャレンジするためのシンプルな環境構築 : ISUCON公式Blog
チームを組む前にさかのぼると、上記を参考に、かいとさんに教わりつつDocker上でISUCON7の環境を構築してみたりしました。と書くとさらっとやった感が出ますが、これすら苦戦しました。WSL2が入ってないと怒られて「ほんまか?」となりながらWSL2をインストールしなおしてそれでも直らず、自分のUbuntuのバージョンが謎に古い(18.04)ぽいことに気づき新しいやつをインストールして、それでも動かずdocker-composeにsudoをつけないとだめだと教わってようやく動かせました。
ベンチは回るようになったものの、2人ともWebサービスを高速化した経験/Zeroだったので、環境構築以降はとくにさわってないです……


本番が近づいてくると、もらったクーポン*2を利用してさくらのクラウド上でISUCON10の問題を3人でさわってみることになりました。
とりあえず計測をしないことにはボトルネックが見つけられないよね、ということで、alp・dstat・pprof・pt-query-digestの使い方を教わりました。

ここで困ったこととして、自分に知識や経験がなさ過ぎてkakiraちゃんの書いてくれた使い方説明書が全然読めない……ということがありました。インストール方法・使い方・注意点をgithubにまとめてくれていたのですが、そのコマンドをどこで打てばいいのか・適切なパスに書き換える必要があるのは分かるけどどこを指定すればいいのかなどが自分で考えても分からなくて、たくさんご迷惑をおかけしました……。

計測ツールの使い方だけをふんわり理解したところで、準備は終了しました。なんてこった。

本番当日

本番はかいとさんの家に3人で集まりました。

さっそくやることが無くなってしまいました。とはいえ、ぐーぐー寝るのもナメとんかお前となってしまうので、まずドキュメントをよく読みます。kakiraちゃんが環境構築をして、その間に私とかいとさんでコード読んだりドキュメント読んだり実際に触ってどんな動きをするのか試してみる、という戦法です(?)


アプリケーションマニュアルのほうは短いですね。予選当日マニュアルのほうは情報量が多くて、後ろの方にスコアの計算方法が書いてあって大事そうだねーと話していました。とくにCriticalなエラーを1つ踏んでしまうとそれだけで10%の減点ということでつらそう。


ところでちゃんと鍵の登録に成功していたのがかいとさんだけで(え?)、残る2人はサーバーにログインできなかったので改めてかいとさんに追加してもらいました。
ssh isucon1……よっしゃ開くぜ!VS Codeのリモートエクスプローラーで中身見るぜ!→接続できません……になりました。練習でも同じミスをしました。なぜか私のパヨヨンのいたるところに.sshフォルダがあるために(?)設定ファイルの指定を間違えていました。改めて正しいファイルを指定しなおすと、今度は3番目のサーバーだけリモートエクスプローラーで読み込めません。解決方法も分からなかったので、とりあえず2番目のサーバーだけ触ることにさせてもらいました。ごめんなさい。


中身を見てみると、ISUCON10ではMySQLやらNginxやらいろんなコンテナが立っていましたが、今回はGoの部分だけ(?)みたいでした。処理はisuports.goに集約されていて、正直まったく読める気がしませんでしたが親切にもたくさんコメントが付いていてふんわり掴めました。

まず目につくのは107行目のfor i := 0; i < 100; i++とかいうやつです。100回も何やってんねんと言うと、 システム全体で一意なIDを生成しようとしてるらしいです。stubとかいうよく分からないstringを持ってるけど'a'以外なんも入れてないし、これは何?という話になりました。
ただこの時点でまだ計測ツールが入っていないので、すぐ直すのではなくてとりあえず改善点メモに書きだすにとどめました(あと単純に二人ともGoを書く自信がない)

排他ロックを多用していてまずそうとかいとさんが教えてくれたので、使ってるところを列挙してみることにしました。確かにこんなんでいちいちロックアンロックとかやってたらよくなさそうだなとは思ったのですが、私は直し方が分かりませんでした。

あとはindex貼ると速くなるみたいな話があったな……と思って、SELECT ホニャララみたいなところでどういう並び順を指定してるのか読んだりしていました。


↑なにかメモを残そうと足掻いていた形跡がありますね。

他には、テナントが追加されるたびにファイルが追加されるのがヤバそう・そもそもSQLiteMySQLが混じってて大変、などという話をしていました。


とりあえず中身をいじっていいことになったので、適当な(そして私でも出来そうな……)改善を考えることにしました。

スギノキ「Nginxのチューニング試したいです」
kakiraちゃん「いいけど、NginxのフォルダはWebappの外にあってgitの管理外だから……」
スギノキ「(ここにチベットスナギツネの画像が入る)」

私がチベットスナギツネになっている間に、kakiraちゃんがシンボリックリンクを張って(?? 何をやっているのか分からなかったのでこの辺嘘かも)NginxのフォルダをWebappの中に移動させてくれました。

nginxのパラメータチューニングとh2o - Qiita
↑これを見ながらほぼコピペしました。
sudo systemctl status isuportsじゃ変更は反映されなくて、sudo systemctl restart nginxじゃないとだめだよーと教わりました。確かに元々Webappじゃないフォルダにあったんだからそれもそう……?

ここ(14時半ごろ)でようやく初ベンチを回してみると、2620点でした。特に変更の恩恵はなさそうですが、適当なブランチにpushしました。


15時ごろ、計測ツールが使えるようになりました。pprofで見てみると、明らかにSQLite部分の処理がクソ遅く、ここが足を引っ張っていることは明らかです。逆に100回for文とかの部分は全体的な比重としては食ってないぽいと。

いとさんSQLite部分を綺麗にMySQLに置き換えられれば速くなりそうですね」
kakiraちゃん「その実装はこの残り時間では無理です……」

それは一旦諦めて、かいとさんがindexを張ったりしてくれていました(たぶん)


いとさんがindex張ったりkakiraちゃんがアプリの内容を把握したり排他ロック外してみたりしてる間に、NginxとWebappがTCPで通信してるのをUnix Domain Socketで書き換えてみることにしました(これも自分一人では結局できなくて、kakiraちゃんにたくさん聞きました……)
Nginxのフォルダの隣に適当なフォルダを作って、そこにapp.sockを置いてyamlのvolumesに書き加えました。
ここでスコアが2852と若干の上昇を見せます。ベンチが通って若干上がったことを報告して、これも適当なブランチを切ってpushしました。


kakiraちゃん「なんかログ出ないなと思ったらNginxのaccess_logがoffになってる!!!!」
何も考えないでoffにしたスギノキ「!!!!!!!!!!!!!!!!!!!!!!!!」
本当にすみません すみません……


kakiraちゃんがロックを全部外してみたところ、スコアが5000超と元気に伸びましたが、10回に1回くらいしかベンチが通らなくなったことが発覚します。この時点で17時を過ぎていて、そろそろ終わりのことを考えないとまずいという状況でした。
さらに、私がmasterブランチにセルフマージした*3やつが、実は他の人がpullすると動かないということも発覚します。原因はapp.sockがなぜかpushできていなかったからです。
いとさんに謝りながら、とにかく時間がないので自分でapp.sockを置いてもらおうとすると、権限周りのエラーでファイルが作れないと出ます。死!

とりあえず、かいとさんが書いたindex張ったやつに一部だけ排他ロックを外した状態で提出しよう、ということになりましたが、間に合わず終了しました。

反省と次回に向けて

  • 何が分からないのか自分でも分からない
  • 環境構築パートを全てkakiraちゃんに押し付けてしまったので何もわからない
  • Goを書く自信がなくて全然触れなかった
  • DBの勉強を全くしていなかった
  • 優先順位をつけた実装ができなくて、意味があるのかもわからないままできそうなところから手を付けてしまった
  • 若さに甘えておやつにアイスを2個食べると腹を壊す


来年は"戦"の土俵に立てるように頑張りたいです。

他の二人も参加記を書いています!
kakira96.hatenablog.com
umineko-sephi.hatenablog.com

*1:しいて言うならJavaを研修で習いたてほやほやだったのですが、例年は参考実装にJavaがないので過去記事を参考にあれやこれやがしにくい

*2:ISUCONに申し込むと練習用に使うさくらクラウドのクーポン・本番用に使うAWSのクーポンがもらえます

*3:完全にいいわけですが一応許可は取った