linotice

linotice

2017.03.08

社内チューニングバトル「Y!SUCON」の優勝はなんと2016年度新卒チーム!

Y!SUCON参加者2名の写真
ヤフーでは既存サービスの質を高めたり、新たなサービスを生み出したりするために社員同士が修練し、スキルアップに努める風土が醸成されています。エンジニアの技術力向上を目的として、社員自らがさまざまなイベントを企画し、実施しているのです。1月に開催された「Y!SUCON」もその一つ。

今回は、そのイベントの様子や運営者の思い、優勝チームがどのようにパフォーマンスチューニングを図ったかなどを紹介します。

技術向上を目的とした社内 ISUCON「Y!SUCON」

「Y!SUCON(ワイスコン)」とはヤフー社内で開催しているプログラミングコンテストで、業務外の時間を利用して行っているものです。有志メンバーが企画し、日常用いられる技術に加え、これまで業務で使ったことのない技術を学ぶ機会を提供しています。

1回目は8月に社内の一部のエンジニアを集めて開催。9割以上の参加者から「勉強になった」という高い評価を得て、このたび2回目の開催となりました。

公式のISUCONはLINEが主催しており、Webサービスを決められたレギュレーションの中で限界まで高速化を図るチューニングバトルです。本来は1日という限られた時間内で勝負するイベントですが、「Y!SUCON」は1週間の長期戦。 公式のISUCONにも技術力で負けたくないという思いから、イベント名も「Y!SUCON」と改称して実施しています。

結果発表の後には懇親会を実施し、各チームが行ったチューニングを発表し合う場を設けています。ルールは用意された課題のボトルネックを発見して性能を高めていき、最終的に1番パフォーマンス向上ができたチームが優勝するというもの。

今回は、前回の運営メンバーに前回優勝メンバーであるシステム統括本部の栗山太希も加わり、サーバープロビジョニングを担当しました。

image
▲ Y!SUCON運営事務局メンバー 問題考案は全員で行っている

チューニングバトル後は、結果発表&懇親会

今回の開催期間は2017年1月13日から1月20日の一週間。この期間の中で、仕事が終わった後や土日を使って作戦会議や作業を進めます。なかには、昼の休憩の合間を縫ってアクションをおこなう人も。

最終日の1月20日。参加者たちは イベント会場に集まり、 19時の締め切り直前まで、最後のチューニングをします。

image
image

20時からは問題の解説や入賞者の発表が行われました。ビールやお寿司、サンドイッチなどの軽食を自由に取りながら、和気あいあいとした雰囲気で進行していきます。皆さん、やりきったあとの安堵(あんど)感でいっぱいのようです。

image
image

問題の狙いは、世間で使われている標準的な技術を学ぶこと

今回の問題の解説は、CTO室 SWAT 柄澤史也から行われました。

「世間一般的な技術を学んでほしいと思い、一般的な技術のみで構築しました。また、SQLの悪い例を実装しておいたり、シーザー暗号、マイクロサービスライクな挙動など、勉強的要素を多く盛り込んだりしています」

image
▲CTO室 SWAT 柄澤 史也

「盛り込んだ内容のわりに開催期間を長く(1週間)設けることで、初心者でもチャレンジしやすく、じっくり解いてもらえるようにしました。

問題のテーマは大きく三つ。第一はキャッシュの効かせづらいサービス。例えばpostされるたびにタイムラインが変更される、同時に複数ユーザーがアクセスするというようなサービスです。

次にSQLアンチパターン。SQL文に明るくない開発者が作成したと想定しました。第三はマイクロサービスです。無駄にサービスを分けています(笑)」

「ISUCON」でやるべきことの基本は次の三つ。

● git管理(巻き戻せるようにするため)
● mysqldumpでバックアップする(うっかりDBを消してしまった場合に備える)
● ボトルネック調査(アクセスログの統計を取る)

アクセスログの統計を取るツールとしては、ISUCON用に開発されたkataribeやalpなども登場しているので、ぜひ活用しましょう。

チューニング例も紹介しています。

● isutomo削除, friendsをidのリレーションに 143 => 161
● WHERE IN, LIKE文, LIMIT 50 161 => 1583
● INDEXを張る 1583 => 4938
● nginx.conf 調整 4938 => 5244
● user_nameの非正規化と事前htmlify 5244 => 17134
● faviconをサーブ 17134 => 26809
● usersテーブルをキャッシュ 26809 => 33019

これで3万点は稼げます。

image

さらに上を目指す人は、

● パスワード認証はシーザー暗号のrot1
● Unix ドメインソケット
● MySQLをメモリエンジンにする
● MySQLをtmpfs上に配置
● MySQLをやめる
● テンプレートエンジンを捨てる
● その他

この辺りについては、ネット上のいろいろなブログに書いてあるので、「ぜひ、検索して調べてほしい」と呼びかけていました。

ログを丁寧に解析したことが優勝の決め手に

今回優勝したのは、なんと2016年度に入社した新卒同期からなるチーム。しかも運営事務局の想定を超える20万点というスコアをたたき出しました!

1位:SUTEKINAANATA
2位:ワイハリマ
3位:僕の名は。

image

上記3チームには賞品が贈られました。

続いて、上位入賞者によるコードの披露とその意図が発表されました。また、1位と2位のチームに受賞の喜びを語ってもらいました。

ベンチマークの挙動に違和感を発見して検証

■1位: 「SUTEKINAANATA」チーム

言語はCrystalを採用しました。当初はデータベースのチューニングなど、正統派で勝負しようと考えていました。着実にスコアを伸ばしていましたが、途中で友達のチームがぐんぐんスコアを伸ばしてきたので、これは危ないと思い、ベンチマークを回してログをとって検証していたら、ベンチマークの挙動に違和感を発見しました。

image
▲1位の「SUTEKINAANATA」チーム
(左)システム統括本部プラットフォーム開発本部 鈴木 太一郎
(真ん中)システム統括本部プラットフォーム開発本部 杉村 憲司
(右)メディアカンパニー検索事業本部 富樫 陸

Y!SUCONのベンチマーカーはランダムに来ているので、それに対して正しい回答をすると思い込んでいたました。しかし、ちょっとしたことからブレークスルーがありました。メンバーの1人がTwitterの本文の内容をすべてhogeにし、ハッシュタグを残したところ、ベンチマークが通ったのです。

つまり本文の内容はゼロでもいいということ。nginxの内容を見るとシナリオは決まっています。それをログで確認して、ユーザーが存在しないWebページを作成しました。そういうことを地道にやる一方で、先ほどの解説にあったことはすべて行いました。

勝因はこのように勝つためだけの実装をしたことです(笑)。Crystalを用いたことも全く関係はありませんでした。でもとにかくすごく楽しかったです。

image

最初は正統派な「このままでは優勝できないか」と「ブレークスルーがないか」を議論していました。ベンチマーカーが規則的に動いていることがわかり、それをうまく利用すれば速くなるのではと考え、ログの解析をがんばりました。

この動きがわかったことで、Tweet本文にどんな文字が入るかを考える必要がありました。優勝の要因はベンチマーカーの挙動の解析を緻密にしたことだと思います。

image

とはいえ、優勝する確信は最後まで持てませんでしたね。他のチームもじわじわと追いかけてきて、最終的には2万点差まで追い詰められたので本当にギリギリでした。

僕たちは新卒の同期3人組なので、このイベントに参加するのは初めてです。先輩から「ぜひ、参加してみたら」と勧められ、参加することにしました。

参加して良かったのは、技術的なことよりもメンバーでいろいろ議論することの大事さを学べたことです。また、大学時代に学んだ基礎を思い出す機会にもなりました。

今回Crystalを使ったのは、好きな言語だったからです。参加を決めたときから、Crystalで行くことを決めていました。Crystalは速いRubyと言われていますから。

ただ、まだ言語としては完成形ではないので、さらに進化していくことを希望しています。次回もぜひ、参加したいと思います。

image
▲入賞者の発表に笑顔で聞き入る参加者たち

前回2位。今回は絶対優勝の意気込みで臨んだ

■2位:ワイハリマチーム

先ほどの解説に登場したような一般的なチューニングを実施し、さらにPHPの構成やコンパイルオプションがよくなかったので、全部消して新しいものを入れた段階で3万点ぐらいに達成しました。

image
▲2位の「ワイハリマ」チーム

(左) システム統括本部プラットフォーム開発本部 播磨 裕太
(右) データ&サイエンスソリューション統括本部サイエンス本部 成川 弘樹

ハッシュタグ要素の検索が11種類しかなかったので、memcacheで11種類のハッシュタグの最新を取るようにしました。また、検索のレパートリーもハッシュタグのワードと同じものしか取らないことがわかったので、ハッシュタグにとばすようにしました。

そのほかにも、CookieにユーザーIDとユーザー名を直接書き込んで認証してPHP のセッション機構を不要にしたり、フレームワークから脱却したりしました。レビューはかなり大変でしたね。

さらに高速化を図るため、すべてをnginxのモジュールにするというような検討もしました。

MySQLも脱却し、初期化時、メインメモリ上に直近数百件の発言を載せるのみとなりました。最終的にはエラーを出しながらもベンチマークが動けば正義だということで、記録する件数を調整してどのくらいまで速度と正確さのトレードオフを図るかで勝負しました。

image

1位になれるかなと思ったときに、1位のチームに10万点ぐらい離されて心が折れることもありましたが、もうやるしかないと思い、自分たちができることは全部やりきろうと思いました。

実は前回、さたけチーム(前回優勝チーム)に負けて2位だったので、今回は優勝を狙っていたんです。スローガンは「打倒さたけ」。

しかし、さたけチームの栗山さんが運営側に回ったことを知り、今回は優勝しかないとさらに意気込んでいたので、この結果は残念でした。

でも1位のチームの発表を聞いて、「これは2位でも仕方がない」と思っています。モックでやってくるとは考えもしませんでしたから。ベンチの動作を解析してくるのはさすがだと思いましたね。僕たちはサービスとして動くことを前提としていて、その予想外の解決策を示してきたことはびっくりしました。

image

僕たちは実サービスの運用に直接携わってはいません。したがって、今回のことが仕事に生かせるかというとそうではないかもしれませんが、個人としては面白い経験ができました。

このイベントでチューニングのコツなどもつかめたような気がします。前回、今回と参加したことでノウハウもたまったので、次こそ優勝を狙いたいですね。次回の本家ISUCONでは、今回学んだことを生かせればよいと思っています。

次回の 「Y!SUCON」 は半年後ぐらいに開催予定です。今後も若手からベテランまでが仕事外でも技術力を磨くことができる環境を作っていきたいと思います。ご期待ください!


採用情報 公式SNSアカウント

このページの先頭へ