indeed indeed - a presentation for indeed なう -
TRANSCRIPT
自己紹介
● 東京理科大学工学部電気工学科卒○ ちゃんと 4 年
● 中堅 SIer○ 2.5 年
● 入社当時十数人だったネット系ベンチャー○ 5 年
● 独立系受託開発会社○ 3.5 年
● リクルート○ じゃらんゴルフ開発 1 年○ Indeed エンジニア 2 年
朝
● 9時〜11時の間に出社する人が多い● スタンドアップミーティング
○ 昨日やったこと / 今日やること○ 作業の調整
■ 「あ、そこんとこお互い関係あるね」「この後詳しく話
そうか」○ 10 分で終了
● 早速コーディング
昼
● フリーランチ○ いまのところ火・水・木の週3日○ 月・金はガーデンプレイス周辺を散策中
● 最近の流行りは将棋とビリヤード○ 他にも卓球、ピンボール、ぷよぷよ、マリカー、ラジコン
などなど○ 要するに好きなことしてると
● がっつりコーディング
夕方
● 引き続きコーディング● ウィークリーミーティング
○ 今週やったこと / 来週やること○ ビール○ 唯一の定例ミーティング - 1 時間 / 週
● ハッピーアワー○ 毎週金曜 17 時頃からゆるりと○ ビール
■ ビール以外のお酒、ソフトドリンクもあるよ
● 17時〜19時の間に帰る人が多い
Indeed エンジニアのコード
● 超アルゴリズムなコードばかり?○ そういうのもある
○ でも Web なんでバックエンドもフロントエンドもその間あ
たりも色々ある
● AB テストめっちゃする○ 何でもデータで評価する○ CEO ですらデータ出さないと周りが納得しない
● 基礎重要○ “無駄に” 重いのはだめ○ データ構造選びはきちんとね
● 何か課題があってそれをどう解決するかの繰り返し
所属するチームの紹介
● カンパニーデータチームに所属● Indeed の持つたくさんの会社情報を表示する
ページ○ 概要・口コミ・写真・給与情報などなど
● それらのデータを Indeed 内の別チームに提供する API○ 検索結果に表示される口コミ評価など
具体例1:ABテスト
課題:最近追加した給与情報ページのアクセスを増やしたい
答え:目立たせる!
本当の課題:どんなデザインが一番効果的か?
イケてるデザイナが考える??
否、AB テストが知っている!
具体例1:ABテスト
● 結果○ A:new! アイコン → 8.86% PV アップ○ B:概要ページチラ見せ → 4.24% PV アップ○ C:サイドバーチラ見せ → 6.97% PV アップ
● new! アイコン採用!
…?
具体例1:ABテスト
● 結果○ new! アイコン → 8.86% PV アップ○ 概要ページチラ見せ → 4.24% PV アップ○ サイドバーチラ見せ → 6.97% PV アップ○ 全部乗せ → 97.14% PV アップ
● 当たり前の結果でもちゃんとテストする○ 仮説に確信を持つため○ 将来の決定に情報を残すため
■ 他の機能の都合上どうしても給与ページの露出を減
らす場合は?■ 概要ページが一番インパクト少ない!
具体例1:ABテスト
● ちなみにこれ、実装、分析から世界中100% のユーザにリリースするまで、わずか 8 営業日の出来事○ 意志決定が早い○ リリースが早い○ AB テストフレームワークが早い○ 分析ツールが早い
具体例2:会社情報 API
● 検索ページのフロントエンド○ 複数のサービス (= API) に平行してリクエストを投げる○ 全部の結果を待ってから情報をまとめて表示する
○ 最低限、検索結果さえあれば他の API のレスポンスは
そんなに待たない○ 全体のスピードが全てに影響する
■ クリック率■ SEO
○ サイトが “生きてること” も超重要■ 仮に API サーバが落ちてもサイト自体は落ちない
具体例2:会社情報 API
課題:検索フロントエンドの要求に応じて会社の 5 つ星評価を 200msec 以内に返す
CPU 時間で見ると膨大な時間に見えるが…
1. ネットワークのレイテンシを含む2. 評価値以外のメタデータも含めて返す3. MAX 200 なので普段は 50 以下にしたい4. 5000万件の会社情報から検索する
フツーにやったら間に合わない
具体例2:会社情報 API
● 答え1:MySQL (RDB)○ フツーの Web っぽい。
○ 5000万件からの検索を数msec で返せるモンスタークラ
スタを用意する?○ オーバースペック。却下。
● 答え2:mongoDB (NoSQL/KVS)○ いまどきの Web っぽい。
○ 要するにディスク上に構築された巨大なハッシュテーブ
ルなので検索はまあまあ早い。○ ネットワークオーバーヘッドが追加になる。○ MySQL と平行してデータのメンテが必要。○ 面倒くさい。却下。
具体例2:会社情報 API
● 答え3:memcached (インメモリキャッシュ)○ フツーの大規模 Web っぽい。○ スピードは申し分ない。○ キャッシュが無ければ通常速度。○ 初回アクセス時は星が表示されない?○ 惜しい!イケてない。却下。
● 答え4:インメモリ DB○ 今ならありかも。
○ プロジェクト発足当時 (4 年前) に選択するにはアグレッ
シブ過ぎた。
具体例2:会社情報 API
● ソート済みの会社 ID 配列をメモリに持つ○ static int[] CMP_ID_ARR = [1, 2, 3, … 5×108];○ 実際には永続化されてるデータを読んでる
● Java の int は符号付き 32 bit 整数○ 5000万件でも高々 200MB○ 4bytes × 50M = 200MB
● 1インスタンスに 256GB メモリ積む時代にケチケチしない○ 全てのインスタンスにこの int 配列を持つ○ memcached サーバアクセスのオーバヘッドも無い
具体例2:会社情報 API
● 会社 ID 配列と同じ順で評価値配列を持つ○ static float[] CMP_RAT_ARR = [3.2, 4.3, 3.8, ...];○ 同じく全部メモリ上
● こういう関係
[ 1, 2, 3, … 1000 … ]
[3.2, 4.3, 3.8, … 3.4 … ]
か ら の
具体例2:会社情報 API
● 会社 ID を見つけたら同じ index を参照
[ 1, 2, 3, … 1000 … ]
[3.2, 4.3, 3.8, … 3.4 … ]● いくつかの主要メタデータは全部こう
[ 1, 2, 3, … 1000 … ]
[ a, b, c, … x … ]
具体例3:AB テストフレームワーク
課題:アクセスしてくるユーザを複数のテストグループにランダムに振り分ける
● 同じユーザはずっと同じグループ● 数学的に (ある程度) 正しくランダム● 違う種類のテストにおいて相関はなし
具体例3:AB テストフレームワーク
● 同じユーザはずっと同じグループ○ 少なくとも各ユーザを識別するユニークキーが必要
● ログイン中のユーザ○ ユーザ ID (=メールアドレス)
● 非ログイン中のユーザ○ Indeed 全体で共有しているトラッキングクッキーの値
同じユーザの識別については問題なし
具体例3:AB テストフレームワーク
● 同じユーザはずっと同じグループ○ ユニークキーごとにどのグループに所属しているか覚え
ておく必要がある
○ テストをリセットする時には過去のグループを削除して振
り分け直す
● しかし常時 100 以上のテストを実施○ 1ユーザあたり 100 レコード保持?○ 1億5000万ユーザ / 月いるのに?
具体例3:AB テストフレームワーク
● 数学的に (ある程度) 正しくランダム○ 正しいシードを使って乱数を発生させる○ 例えば、現在時刻 XOR hash(ユニークキー) とか
● 違う種類のテストにおいて相関なし○ 乱数の使いまわしはせず、グループ振り分けを行う度に
異なる乱数を発生させる
○ 疑似乱数発生器が十分確からしくランダムなら、シード
の再設定までは要らない (はず)● しかし常時 100 以上のテストを実施
○ 毎回 100 回以上も乱数発生させるの?○ 1億5000万ユーザ / 月いるのに?
具体例3:AB テストフレームワーク
● 同じユーザはずっと同じグループ○ ユニークキーごとにどのグループに所属しているか覚え
ておく必要がある○ 100×1億5000万も覚えておかない
● 数学的に (ある程度) 正しくランダム● 違う種類のテストにおいて相関なし
○ 正しいシードを使って乱数を発生させる
○ 乱数の使いまわしはせず、グループ振り分けを行う度に
異なる乱数を発生させる○ そもそも乱数使わない
具体例3:AB テストフレームワーク
● 各テストごとにユニークな Salt を持つ● ユーザのユニークキー×Salt のハッシュを計算
する● ハッシュ値を 100 で割ったあまりをとる● 0~49 → グループA、50~99 → グループB
hash(unique_key XOR test_salt) % 100
※だいたいの概念。本当はもうちっと複雑。
具体例3:AB テストフレームワーク
● 十分に “良い” ハッシュ関数があれば○ ユーザのユニークキーが決定した瞬間に、ユーザのグ
ループは潜在的に決定済み○ グループの振り分けは十分にランダム○ 振り分けの計算は常に O(1)○ Salt が変わればグループ分けに相関なし
○ あえて Salt を同じにすることで、異なるテストのグルー
プ分けをあえて同じにすることもできる
○ グループ分けの割合を変更した場合も、なんら再計算の
必要が無い
いいことづくめ!
具体例3:AB テストフレームワーク
● このフレームワーク● Proctor という名前でオープンソース化済み
http://indeedeng.github.io/proctor/
● AB テスト結果の分析に適したツールも● Imhotep という名前で同じくオープンソース化済
み
http://indeedeng.github.io/imhotep/