午後から→オーバークロックスマートフォン用の表示で見る午後から→オーバークロック駆け出しハッカー()によるプログラミング・サービス開発備忘録。この広告は、90日以上更新していないブログに表示しています。2014-09-29初心者二人でISUCON予選に突撃して予想通り撃沈したよその他-コンテスト結局ISUCONの予選は惨敗の結果だったわけですが、当日の流れを書き起こしておきたいと思います。Contestの略で、お題となるWebサービスを決められたレギュレーションの中で限界まで高速化を図るチューニングバトルです。「こんなコンテストがあるよ!」ということで紹介してくれました。初心者二人で予選に参加する事にしました。準備したこと方針まずWebアプリの言語について決めました。「予選の突破も大事だけど、やっぱり勉強のためというモチベーションも大事にしたいから、どうせなら新しい言語でやろう!」ということでNode.jsに決定しました。事前に色々な先人達のブログを読んでみました。最初にサービス全体を把握する事が大事そうだ。仕様書読んだり、動いているツールを把握したり。ボトルネックを認識するのが鍵となりそう。やってするの?勘なのか、セオリーがあるのか。Memcached?)のが良さそうキャッシュ・キャッシュ・キャッシュ過去問を解いてみる去年のISUCON3の環境がAWSのAMIの形で提供されていたので、前日の夜から少しいじってみる。二人ともそれぞれAWS立ち上げ。MySQLが立ち上がらなくて困る。startだと立ち上がった。なんじゃそりゃ!(おかげでプロセスの監視とかのコマンドにちょっと詳しくなった)ベンチマークを走らせる。nginxというサーバが速いらしいので、Apacheからnginxに移行してみる。いれば、Webアプリケーションは初期状態でPerlが動いているらしいのだが、ApacheはどこでPerlに処理を渡してるんだ?どうやらlocalhost:5000に投げているみたい。nginx.confでルートに来たリクエストを全部5000に投げるように編集。ここでCSSが読み込まれない自体発生。要素を検証でリクエストヘッダ読んでみると、なんかCSSをlocalhost:5000から読もうとしてる...。$host;書いたら直った。スコアは50くらいアップ。なんとなくNode.js周りを読んで理解してみる。npmでパッケージ入れれるっぽい。最初自分だけなぜかパス通ってなくてはまった。Node.jsに切り替えてみた結果、スコアが数百くらい下がった。ここで予選当日の朝5時くらいだったのでもう寝ました。予選詳細とんだ失態だったのが、二人とも朝寝坊し、10:30くらいに起きたことでした(しかも友人のSkypeで起こされる)。今では目も当てられない、インフラ経験が少ない事によるあまりに浅はかな言葉を放っていました。最初は予習を生かしてとりあえずnginx+Node.jsに環境を変えて動かしてみよう!ということで作業に入りました。したら最初からまさかのnginxだったので、アプリをNode.jsに変えてサービスにアクセスしてみました。動いているのを確認した後、ベンチマークを動かしました。ここでスコア1400くらいで、ISUCONの予選専用サイトで順位を確かめると70位くらい。49ersというチーム名(同じ高校の49期生)だったので、とりあえず49位目指すか、という感じで作業に取りかかり始めました。現状分析ボトルネックを把握しよう!ということで友人が調べて来たnewrelicというサービスを使ってサービスを解析してみました。結局得た情報は「/loginへのリクエストが時間掛かってるな!」というだけ。そりゃそうかという感じ。次に、色々いじりまくってベンチマーク通らなくなったら大変だから、gitで管理しようかー、ということでgitで管理し、BitBucketにプライベートリポジトリつくってpushする形式にしました。普段の開発じゃなかなか無さそうなんでISUCON永遠の命題なのでは無かろうか。それじゃあソースコードを読んでみようかということで、App.jsを読み始めました。時間のかかったクエリを検知する様に、そのクエリを中心に解読していきました。分かった事は、ログインしてmypageに飛ぶ機能だけがあるフィッシング銀行サイト3・10回連続でログインミスったユーザ・IpはBANするサーバでアクセスログを管理してて、最後に成功して以降のミスった回数とかカウントしててめっちゃ重そうデータベース自体の容量は数十MBと、そんなに大きくない。そこで以下のような作戦を取る事にしました。アクセスログからいちいち計算するんじゃなくて、最後に成功してからミスった回数を保持しとこうベンチマーク立ち上げの際の初期化で、元からあるアクセスログからfail数を事前に計算してデータをmemcachedに置いておこう本当はNode.js上でずっとデータを保持しておけばいいんじゃないかと思いましたが、リクエストを処理するプロセスは1つでは無いのでデータ共有が難しそうだし、かといってプロセスを1つにするとマルチコアの恩恵が受けられなくなるのでmemcachedにしました。僕は初期化スクリプトをPythonで書いて、友人はApp.jsの、現在SQLクエリを毎回発行して処理している部分を書き換える事にしました。結果を出せなくて悔しかったですが、立てた作戦通りの実装をした場合にどれだけのスコアが出るか知りたかったので、そのまま寝ずに実装してみました。休憩をしたりサッカーを見たりしながら朝まで頑張った結果、failしないようになって、最終スコアが5500くらいでした(nemupm/isocun4_pre・GitHub)。実装でつまづいてた点は、データがmemcachedのメモリサイズ上限値を超えてて一部が消えてた。memcachedとのやり取りの際にJSONにシリアライズとかしないといけないことに後で気付いた。リクエストのうちカバーできていないパターンが結構あったという感じでした。初期化もjsでやってシリアライズ不要にしたほうが良かったんだろうなと思いました。デバッグがすごく難しかったです。他の方のブログとか読んでると、nginxのアクセスログを独自に分析したりして必要な情報を集めていて、感心した。方針は割と本質とずれてなかったと思うけど、実装力なさ過ぎぃ!インフラ知識が無さすぎて、「こういう時はこうする」という常識が無くて時間がかかったり、SQL以外のボトルネックの把握が出来なかった。ISUCONに参加してみて今回本当に良かったなと思ったのは、僕に足りない知識の部分ってのが具体的に見えたことです。終わった後もidobataでチャットを眺めたりブログを読んで色々考えて、というように、すごく楽しく取り組めたのが最高でした。友人に書けと言われたので書きます。»プロフィールid:nemupmITエンジニアを目指している大学生。参加グループプログラミングはてなブログをはじめよう!nemupmさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。