ISUCON3予選で何も出来なかった話 #isucon

YAPCYAPC::Asia 2013 で「社内ISUCONのつくりかた」を発表しました - 酒日記 はてな支店に刺激されたので ISUCON に会社の後輩と参加しました。
もともと3名で登録してたけど、インフラ方面の頼みの綱がこれなくなっててんやわんやした結果、ほとんど何も出来ずに終わってしまった。もともとアプリ寄りなのでインフラとか全然わからなかった。

やったこと

作業ログは残してあるけど時間軸が記憶頼みなので適当に記載。

事前準備

1時間前に会社について方針を練る。とりあえず、序盤は top で概要把握して、おそらく DB が序盤のボトルネックになるだろうからスロークエリの出し方とか予習してた。
あとは前回・前々回の参加者ブログ*1を読み返してた。

序盤

AWS はちょくちょく使ってたので大丈夫だと思っていたけど、Quick Launch Wizard から Key Pair 変更できなかったりなんなりで20分ほど出遅れる。
SSH で接続できるようになったらとりあえず README 読んでアプリを nodejs に切り替えてから最初のベンチを取った*2。ちなみに、lingr 見て supervisord についてググってってしてたらこの時点で11時近くになってた気がする。初期スコアは確か1000ちょいだったかな。
とりあえず、ベンチ取りながら top 見てると案の定 MySQL に負荷がかかってるみたいなので、自分はそっちの調査とチューニングをして後輩にはアプリのコードで怪しそうな処理がないか見てもらうことに。バージョン管理とかどうしようか考えたけど、とりあえず webapp 以下を git init しておいた。
そういえば、後輩にはアプリのコードとは別にベンチマークツールの挙動を解析してもらおうと思ったけどバイナリだったので諦めた*3。そりゃそうか。
mysql 入って show variables でスロークエリが OFF なのを確認。isucon ユーザでは設定書き換えれなかったので my.cnf を探す。 my.cnf が /usr/my.cnf しかみつからなかったので、無視して sudo vi /etc/my.cnf にスロークエリの設定だけ書く。

[mysqld]
slow_query_log = ON
long_query_time = 0.01

ベンチ回して mysqldumpslow で確認したので片っ端からインデックスはった。created_at は不要かもしれないとは思ったけど、既存データがちゃんと id 順で入ってるのか確認するのが面倒だったので後回し*4

ALTER TABLE memos ADD INDEX is_private(is_private);
ALTER TABLE memos ADD INDEX list(is_private,created_at,id);
ALTER TABLE memos ADD INDEX user(user,created_at);

インデックスはった後、公式のベンチ実行時に DB リセットされるのに気付き、lingr を見つつ init 用のファイルを作成。インフラ力*5が無くて exit 0 とファイルの実行権限ではまったけど、ここまででスコアは 2000 前後。
途中後輩が毎回 username を users テーブルから取ってきてるのを見つけたので、username を memos に持つように指示。/memo で older と newer の計算も重そうだと言ってたで、SQL 1本に出来そうだと思ったけど早くなるか微妙だと判断したため後回しに。ちなみに、この判断は間違ってたっぽい。
初期化スクリプトで既存データにも username 持たせないといけないのでそれに着手しようとしたところで 12 時過ぎていたのでお昼に。

中盤

昼ごはんを食べながらせめてスコア 5000 位はいかないとなーとか話してた。

後輩が username 周りの実装が終わったので、初期化スクリプトで以下の SQL を読みこませるようにした。

    /** ADD COLUMN **/
    ALTER TABLE memos ADD `username` varchar(255) NOT NULL AFTER user;

    /** UPDATE username in memos table **/
    UPDATE memos, users
       SET memos.username = users.username
     WHERE memos.id = users.id;

    /** ADD INDEX **/
    ALTER TABLE memos ADD INDEX is_private(is_private);
    ALTER TABLE memos ADD INDEX user(user,created_at);
    ALTER TABLE memos ADD INDEX list(is_private,created_at,id);

これでスコアは 2400 くらい出た。
後は、node のログを見てると /js, /css, /img とかの静的ファイルを返していたので、静的ファイルは Apache で返そうと試みる。みんな簡単に「静的ファイルをApacheで返すようにした」とか言ってるので簡単そうに思ってたけどここで大ハマリした。テンパってたのと Apache 力の低さと、途中で Varnish か memcached で返そうとか思ってグチャグチャしてるうちにベンチ通らなくなって詰んだ。基本から勉強しよう。
後輩には、ログをざっと見た感じ /recent とかが重そうって言ってあって、それを考慮しつつアプリ側の細かい修正をしてたようだけど、ここらへんから情報共有してる余裕がなくて余り把握していない。

終盤

結局ベンチ通らないまま原因がわからなかったので、残り1時間くらいでインスタンスを新しく立ち上げてそちらにこれまでの作業を移行することに。移行自体は10分程度で終了し*6、公式ベンチをまわしてみるとスコアが 2000 に下がってた。なぜ?
最後のあがきで ApacheMySQL のパラメータ・チューニングを試みるも大きな効果はなし。
後輩が /memo の older と newer の件を思い出したけど時既に遅く、両方見つけたらループから抜けるという適当な処理を入れて最後のベンチを取ろうとしたらタイムアップ。最終的にスコア 2600 台が出たけど送信できず。

反省点

  • 会社にドンピシャな書籍がいくつかあったのに Web の情報ばかりに頼ってしまった。本を読もう。
  • まずアプリの内容を把握しておくべきだった。Markdown 変換の処理に終了後まで気づかず*7。アプリちゃんとみてればもう少しやれることがあったな。
  • 後回しにしたタスクの棚卸し大事。
  • --workload の意味に気づかず。ただ負荷が上がるだけのストイックモードなのかと思った。負荷が上がるということは捌ける数も下がってスコア下がるんだろうなという安直な発想してしまった。んなオプションあるわけない。
  • インフラ力がたりない。もう少し色々弄らないとな、nginx 触ってみよう。

まとめ

基本的なことすら出来ず残念*8でした。ただ、普段やらないインフラ周りの設定とか勉強できたのでかなり学びが有ったし楽しかった。@fujiwara さん @acidlemon さん始め、運営のみなさんありがとうございました!

Java 実装あったら嬉しかったかも。

*1:特にチームfujiwara組を中心に

*2:LL系で二人ともわかるのがJavaScriptだった

*3:リバースエンジニアリングまでは流石にやらない

*4:すっかり忘れてたのでその後着手せず……

*5:常識

*6:ここまで大した作業をしていないということ

*7:画面見た時点で気づけ

*8:実質インデックスはったのみ

YAPC::Asia Tokyo 2013 でボランティアスタッフしてきた

YAPC 楽しかったですね!!
「ブログを書くまでが YAPC です。」って参加者の皆さんに言い続けたので1年以上ぶりにブログ書きます。
多分来年は全然違う形になると思うけど、今年の YAPC::Asia ボランティアスタッフの流れとか書いときます。

ボランティアスタッフ応募

6月に YAPC のチケット販売が始まったので即買いしたら、その後ボランティアスタッフ募集が有ったのでそっちに切り替えました。Perl コミュニティ好きだけど自分は Perl わからない人なので、普通の参加者よりボランティアの方が楽しそうだと思い応募。
YAPC::Asia Tokyo 2013 ボランティアスタッフ募集します!

ボランティア説明会(キックオフ)

応募後しばらくメールも何も来ないなーと思ってたら唐突にYAPC運営のメーリス飛んできて「これを読んでいるあなたはボランティアスタッフだよ」って感じでした。
7月中に説明会と言う名のキックオフをして、次に合うのは当日でした。メーリスが飛んでくるので、着々と進んでる感を眺めながらワクワクしてました。

前夜祭当日

日吉に到着してすぐさま1000人前後の来場者向けにノベルティをせっせと詰める作業。心を無にしながら伸びない締切にデスマを重ねていました。楽しかったです!
受付を開始してからはスピーカー、個人スポンサー、一般の3種類あるTシャツをひたすら畳む作業。レアなサイズのシャツがなかなか見つからなくてトレジャーハンターみたいな気分でした。楽しかったです!
前夜祭中はメインホールの椅子にチラシ(椅子ポンサー)を張ったり、提灯吊るしたりしてました。
前夜祭が終わったら1日目の打ち上げに軽く HUB へ行って明日に備える感じ。他の参加者も当然のように HUB にいてスゴイことになってた。

1日目

キーノート中に他会場の準備を完了して、あとはタイムキーパーとビデオを気にかけるのと幕間にCMを流すのの繰り返し。他のスタッフと調整して聞きに行きたいセッションもちゃんと行けました。
聞いたセッションはこちら

GitDDLやばい!

きれいなコード書ける学生スゴイなー

マニアックな!

波動拳で拍手が!

Perl でも Heroku でも動くんだ!

安定の moznion 氏

Cookie を 0 click で!?

クイズはほぼ惨敗しました

懇親会は無限に出てくる茶色い食事が旨くてやばかった!
懇親会後は明日の準備も特にないので打ち上げに。 HUB がいっぱいだったのけど飲み会幹事長の執念で居酒屋の10人席の個室に20人あがり込むという暴挙!楽しかったです!

2日目

聞いたセッションはこちら

ISUCON 出ようと決意した!

Perl 6 は互換性がない!?

豪華サポーター陣!

LT中に撤収はあらかた終了し、クロージングが開始するころにはステージ裏で待機。引退宣言に動揺しつつ壇上で恒例のスタッフ集合写真とって玄関で参加者のみなさんをお見送りしました。その後のゴミ・備品出し等はあっという間に終了。
3日連続の打ち上げに行って2次回行って朝帰るコースでした!楽しかったです!

感想

YAPC::NA 2013 では "Future Perl is You!!" が話題になったみたいですが、YAPC::Asia 2013 は "Future YAPC is You!!" で締めましたね!
これからも Perl をバリバリ書くことはないだろうけど、Perl コミュニティ界隈には顔出したいなーと思った YAPC でした!
最後に、牧さん、941さんありがとうございました!その他のスタッフやスピーカー、参加者の皆さんもありがとうございました!楽しかったです!

アドテク検定クイズ(初級編)を勝手に解説してみた

去年の年末のサイトリニューアルから猛烈な勢いで良質なアド関連記事を投稿し続けているスケールアウトさん。
アドテク検定クイズ(初級編)が初級のくせにマニアックで難しいと評判だったので各問題にツッコミ入れてみる。

f:id:ikosin:20120118212736p:plain

ちなみに、初見はカウントダウン焦りまくって6点/10問(~_~;)
問題は固定で10問

※ネタバレ注意






Q1.バナーを見たけどクリックしないでコンバージョンしたコンバージョンを何と言う?

  • ポストビューコンバージョン
  • ポストクリックコンバージョン
  • ビジブルコンバージョン
  • ハイブリッドコンバージョン

A1.ポストビューコンバージョン

えっ、ビュースルーコンバージョンじゃないの!?選択肢にないよ??ポストインプレッションとも言うけど。。。
とかやってるうちに時間がなくなりました。
Google先生に聞いてもそんな言葉ないし、ポストクリックコンバージョンの派生で答えればよかったのかな?

ちなみに、クイズから2日後の記事(コンバージョンについて勉強してみる)に以下のような記述が。

コンバージョンの2つの種別
オンライン広告キャンペーンの効果によるコンバージョンかどうかを判定するために以下の2種別のコンバージョンを正確に計測、集計しています。


ポストクリックコンバージョン
広告バナーがクリックされてからコンバージョンに至った数
(中略)
ポストビューコンバージョン
広告バナーをビューしてからコンバージョンに至った数(クリックはしなかった)

うん、社内用語っぽいね(違ってたらすいません)。

Q2.次のうちA/Bテスティングサービスはどれ?

  • KISS Metrics
  • Lotame
  • Optimizely
  • TURN

A2.Optimizely

それぞれのサービスはこちら
KISS Metrics:アクセス分析サービス
Lotame:データアグリゲータ
Optimizely:A/Bテスト
TURN:DSP

Q3.CPDはどういう意味?

  • Cost Per Direct
  • Cost Per Duration
  • Cost Per Domain
  • Cost Per Dimension

A3.Cost Per Duration

Cost Per Dayじゃないの?
うーむ、そもそもDurationって単語知らない。

Direct:直接
Duration:持続
Domain:ドメイン
Dimension:次元

Q4.世界初のバナー広告はどこのサイトがはじめた?

A4.wired.com

まあなんとなくYahoo! FranceGoogleでは無いとは思った。

Wired.com は日本でもWIRED.jpで面白い記事出してるし。
About.comAll Aboutの元ネタみたいなもの。

Q5.バナーの露出回数をユーザーごとに制御する機能を何と言う?

  • インタラクティブコントロール
  • ビューコントロール
  • フリークエンシーコントロール
  • インプレッションコントロール

A5.フリークエンシーコントロール

frequencyはもともと頻度とかの意味で、接触頻度を示す値に使われる。
つまりフリークエンシーコントロールは露出頻度をコントロールするということ。

インタラクティブコントロールは特にWeb広告用語ということではなく、対話的に設定や制御ができるソフトとかデバイスに使わる言葉(多分)。

あと、ビューはページが表示された回数でインプレッションは広告そのものが表示された回数となる。近いけど露出回数の制御ではない。

Q6.第三者配信のメリットは?

  • タグ無しでコンバージョン計測
  • 3スクリーン間で同一ユーザーを判定
  • 配信速度の改善
  • グローバルフリークエンシーコントロールの有効化

A6.グローバルフリークエンシーコントロールの有効化

第三者配信の説明は省略。
複数のメディアに表示される広告でもまとめて管理しているのでネット全体でフリークエンシーコントロールが可能ということかな。

Q7.CPC50円でCTRが0.08%だった時のeCPMは?

  • 400円
  • 4円
  • 4,000円
  • 40円

A7.40円

これは単純に暗算。
eCPMは< effective Cost Per Mill >の略で、Millってのは馴染みが薄いけど1/1000 ドルの事。
1000インプレッションにおけるコストの事なので計算式はこんな感じ。
50×0.08÷100=0.04 (1インプレッションあたりの単価)
0.04×1000=40

Q8.次のうちアクセス解析サービスはどれ?

  • AppNexus
  • AdBrite
  • MediaMath
  • ChartBeat

Q8.ChartBeat

ChartBeat以外は知らないサービスだった。

AppNexus: DSP+アドエクスチェンジ
AdBrite:アドエクスチェンジ
MediaMath:DSP
ChartBeat:リアルタイムアクセス解析

Q9.バナーの露出間隔をユーザーごとに制御する機能をなんと言う?

  • リーセンシーコントロール
  • スペースコントロール
  • スケジュールコントロール
  • タイムコントロール

A9.リーセンシーコントロール

こちらは露出回数ではなく、露出間隔のコントロールについて。
直前に接触した広告が購買行動に影響を与える効果の事をリーセンシー効果と言うらしい。知らなかった。
他の選択肢は間隔のコントロールっぽい誤答を誘導する言葉かな。

Q10.ミディアムレクタングルのサイズは?

  • 160 x 600
  • 300 x 250
  • 728 x 90
  • 468x60

A10.300 x 250

バナーの大きさに業界のガイドラインがあるらしい。
Wikipediaでまとめられていたのでそちらを参照。
バナー - Wikipedia




以上、知らないことも多くて勉強しないといけないと思わせるクイズでした。
サクっとGoogle先生に聞いただけの解説なんで間違ってたら指摘して下さい。

次回の中級編にも期待してます。