Submit Search
indeed Indeed - a presentation for Indeed なう -
•
14 likes
•
4,030 views
Toru Ochiai
Follow
Indeed なうで行ったプレゼンのスライドです。
Read less
Read more
1 of 81
Download now
Downloaded 20 times
More Related Content
indeed Indeed - a presentation for Indeed なう -
1.
indeed Indeed〜 実際のとこどうなの?Indeed
さん! 〜 Toru Ochiai Software Engineer @ Indeed Tokyo
2.
自己紹介
3.
自己紹介 ● 東京理科大学工学部電気工学科卒 ○ ちゃんと
4 年 ● 中堅 SIer ○ 2.5 年 ● 入社当時十数人だったネット系ベンチャー ○ 5 年 ● 独立系受託開発会社 ○ 3.5 年 ● リクルート ○ じゃらんゴルフ開発 1 年 ○ Indeed エンジニア 2 年
4.
自己紹介 …は いったん 置いておいて
5.
自己紹介 唯一 重要な キーワード
6.
自己紹介 お っ ち ー “otchy”
7.
自己紹介 otchy
8.
自己紹介 .net Twitter Qiita .com
9.
自己紹介 全部 ぼくです
10.
Indeed エンジニアの 一日
11.
朝 ● 9時〜11時の間に出社する人が多い ● スタンドアップミーティング ○
昨日やったこと / 今日やること ○ 作業の調整 ■ 「あ、そこんとこお互い関係あるね」「この後詳しく話 そうか」 ○ 10 分で終了 ● 早速コーディング
12.
昼 ● フリーランチ ○ いまのところ火・水・木の週3日 ○
月・金はガーデンプレイス周辺を散策中 ● 最近の流行りは将棋とビリヤード ○ 他にも卓球、ピンボール、ぷよぷよ、マリカー、ラジコン などなど ○ 要するに好きなことしてると ● がっつりコーディング
13.
夕方 ● 引き続きコーディング ● ウィークリーミーティング ○
今週やったこと / 来週やること ○ ビール ○ 唯一の定例ミーティング - 1 時間 / 週 ● ハッピーアワー ○ 毎週金曜 17 時頃からゆるりと ○ ビール ■ ビール以外のお酒、ソフトドリンクもあるよ ● 17時〜19時の間に帰る人が多い
14.
Indeed エンジニアの一日 要するに Indeed の エンジニアは
15.
Indeed エンジニアの一日 コーディングと ビールから 出来ています
16.
Indeed エンジニアの一日 じゃあ実際 どんなコード 書いてんの?
17.
Indeed エンジニアの コード
18.
Indeed エンジニアのコード
19.
Indeed エンジニアのコード …って 話じゃなくて
20.
Indeed エンジニアのコード ● 超アルゴリズムなコードばかり? ○
そういうのもある ○ でも Web なんでバックエンドもフロントエンドもその間あ たりも色々ある ● AB テストめっちゃする ○ 何でもデータで評価する ○ CEO ですらデータ出さないと周りが納得しない ● 基礎重要 ○ “無駄に” 重いのはだめ ○ データ構造選びはきちんとね ● 何か課題があってそれをどう解決するかの繰り 返し
21.
Indeed エンジニアのコード 具体例を紹介 …の前に
22.
所属するチームの紹介 ● カンパニーデータチームに所属 ● Indeed
の持つたくさんの会社情報を表示する ページ ○ 概要・口コミ・写真・給与情報などなど ● それらのデータを Indeed 内の別チームに提供 する API ○ 検索結果に表示される口コミ評価など
23.
所属するチームの紹介 ● 会社情報ページ
24.
所属するチームの紹介 ● 会社情報 API
25.
具体例1 ABテスト
26.
具体例1:ABテスト 課題:最近追加した給与情報ページのアクセスを 増やしたい 答え:目立たせる! 本当の課題:どんなデザインが一番効果的か? イケてるデザイナが考える?? 否、AB テストが知っている!
27.
具体例1:ABテスト ● グループ A:new!
アイコン
28.
具体例1:ABテスト ● グループ B:概要ページでチラ見せ
29.
具体例1:ABテスト ● グループ C:サイドバーでチラ見せ
30.
具体例1:ABテスト ● 結果 (給与情報ページの
PV) 何も無し(既存) グループA グループB グループC
31.
具体例1:ABテスト ● 結果 ○ A:new!
アイコン → 8.86% PV アップ ○ B:概要ページチラ見せ → 4.24% PV アップ ○ C:サイドバーチラ見せ → 6.97% PV アップ ● new! アイコン採用! …?
32.
具体例1:ABテスト ● 結果 (給与情報ページの
PV) ?
33.
具体例1:ABテスト ● 結果 ○ new!
アイコン → 8.86% PV アップ ○ 概要ページチラ見せ → 4.24% PV アップ ○ サイドバーチラ見せ → 6.97% PV アップ ○ 全部乗せ → 97.14% PV アップ ● 当たり前の結果でもちゃんとテストする ○ 仮説に確信を持つため ○ 将来の決定に情報を残すため ■ 他の機能の都合上どうしても給与ページの露出を減 らす場合は? ■ 概要ページが一番インパクト少ない!
34.
具体例1:ABテスト ● ちなみにこれ、実装、分析から世界中100% の ユーザにリリースするまで、わずか
8 営業日の 出来事 ○ 意志決定が早い ○ リリースが早い ○ AB テストフレームワークが早い ○ 分析ツールが早い
35.
具体例1:ABテスト スピード重要
36.
具体例1:ABテスト 何度もテストを 繰り返し 最適解に近づく
37.
具体例2 会社情報 API
38.
具体例2:会社情報 API ● 検索ページのフロントエンド フロントエンド 検索
API 会社情報 API認証 API などなど フロントエンド
39.
具体例2:会社情報 API ● 検索ページのフロントエンド ○
複数のサービス (= API) に平行してリクエストを投げる ○ 全部の結果を待ってから情報をまとめて表示する …と思うじゃないですか
40.
具体例2:会社情報 API (再び) スピード重要
41.
具体例2:会社情報 API ● 検索ページのフロントエンド ○
複数のサービス (= API) に平行してリクエストを投げる ○ 全部の結果を待ってから情報をまとめて表示する ○ 最低限、検索結果さえあれば他の API のレスポンスは そんなに待たない ○ 全体のスピードが全てに影響する ■ クリック率 ■ SEO ○ サイトが “生きてること” も超重要 ■ 仮に API サーバが落ちてもサイト自体は落ちない
42.
具体例2:会社情報 API ● 通常の検索結果 関連会社情報 オートコンプリート 5つ星評価 ログインリンク
43.
具体例2:会社情報 API ● 検索ページのフロントエンド フロントエンド 検索
API 会社情報 API認証 API などなど フロントエンド タイムアウト
44.
具体例2:会社情報 API ● 調子悪い時の検索結果 関連会社情報 表示されない オートコンプリート 出来ない 5つ星評価表示されない ログイン出来ない
45.
具体例2:会社情報 API 課題:検索フロントエンドの要求に応じて会社の 5 つ星評価を
200msec 以内に返す CPU 時間で見ると膨大な時間に見えるが… 1. ネットワークのレイテンシを含む 2. 評価値以外のメタデータも含めて返す 3. MAX 200 なので普段は 50 以下にしたい 4. 5000万件の会社情報から検索する フツーにやったら間に合わない
46.
具体例2:会社情報 API ● 答え1:MySQL
(RDB) ○ フツーの Web っぽい。 ○ 5000万件からの検索を数msec で返せるモンスタークラ スタを用意する? ○ オーバースペック。却下。 ● 答え2:mongoDB (NoSQL/KVS) ○ いまどきの Web っぽい。 ○ 要するにディスク上に構築された巨大なハッシュテーブ ルなので検索はまあまあ早い。 ○ ネットワークオーバーヘッドが追加になる。 ○ MySQL と平行してデータのメンテが必要。 ○ 面倒くさい。却下。
47.
具体例2:会社情報 API そもそも ディスクIO(~10ms)が 遅い
48.
具体例2:会社情報 API メモリ(~100ns)と 105 も オーダーが違う
49.
具体例2:会社情報 API ● 答え3:memcached
(インメモリキャッシュ) ○ フツーの大規模 Web っぽい。 ○ スピードは申し分ない。 ○ キャッシュが無ければ通常速度。 ○ 初回アクセス時は星が表示されない? ○ 惜しい!イケてない。却下。 ● 答え4:インメモリ DB ○ 今ならありかも。 ○ プロジェクト発足当時 (4 年前) に選択するにはアグレッ シブ過ぎた。
50.
具体例2:会社情報 API Indeed の答え
51.
具体例2:会社情報 API 意外なほど単純
52.
具体例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 サーバアクセスのオーバヘッドも無い
53.
具体例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 … ] か ら の
54.
具体例2:会社情報 API おもむろに バイナリサーチ
55.
具体例2:会社情報 API ● 会社
ID を見つけたら同じ index を参照 [ 1, 2, 3, … 1000 … ] [3.2, 4.3, 3.8, … 3.4 … ] ● いくつかの主要メタデータは全部こう [ 1, 2, 3, … 1000 … ] [ a, b, c, … x … ]
56.
具体例2:会社情報 API 難しい問題を シンプルに解く
57.
具体例2:会社情報 API 常にシンプルな 方法を考える
58.
具体例3 ABテスト フレームワーク
59.
具体例3:AB テストフレームワーク 課題:アクセスしてくるユーザを複数のテストグ ループにランダムに振り分ける ● 同じユーザはずっと同じグループ ●
数学的に (ある程度) 正しくランダム ● 違う種類のテストにおいて相関はなし
60.
具体例3:AB テストフレームワーク 3つの要求を 満たす実装を 考えてみる
61.
具体例3:AB テストフレームワーク ● 同じユーザはずっと同じグループ ○
少なくとも各ユーザを識別するユニークキーが必要 ● ログイン中のユーザ ○ ユーザ ID (=メールアドレス) ● 非ログイン中のユーザ ○ Indeed 全体で共有しているトラッキングクッキーの値 同じユーザの識別については問題なし
62.
具体例3:AB テストフレームワーク ● 同じユーザはずっと同じグループ ○
ユニークキーごとにどのグループに所属しているか覚え ておく必要がある ○ テストをリセットする時には過去のグループを削除して振 り分け直す ● しかし常時 100 以上のテストを実施 ○ 1ユーザあたり 100 レコード保持? ○ 1億5000万ユーザ / 月いるのに?
63.
具体例3:AB テストフレームワーク ● 数学的に
(ある程度) 正しくランダム ○ 正しいシードを使って乱数を発生させる ○ 例えば、現在時刻 XOR hash(ユニークキー) とか ● 違う種類のテストにおいて相関なし ○ 乱数の使いまわしはせず、グループ振り分けを行う度に 異なる乱数を発生させる ○ 疑似乱数発生器が十分確からしくランダムなら、シード の再設定までは要らない (はず) ● しかし常時 100 以上のテストを実施 ○ 毎回 100 回以上も乱数発生させるの? ○ 1億5000万ユーザ / 月いるのに?
64.
具体例3:AB テストフレームワーク つまり 難しいのは ここ
65.
具体例3:AB テストフレームワーク 100テスト 1億5000万ユーザ
66.
具体例3:AB テストフレームワーク ここで再び シンプルな方法を 考える
67.
具体例3:AB テストフレームワーク Indeed の答え
68.
具体例3:AB テストフレームワーク ● 同じユーザはずっと同じグループ ○
ユニークキーごとにどのグループに所属しているか覚え ておく必要がある ○ 100×1億5000万も覚えておかない ● 数学的に (ある程度) 正しくランダム ● 違う種類のテストにおいて相関なし ○ 正しいシードを使って乱数を発生させる ○ 乱数の使いまわしはせず、グループ振り分けを行う度に 異なる乱数を発生させる ○ そもそも乱数使わない
69.
具体例3:AB テストフレームワーク それで実現可能?
70.
具体例3:AB テストフレームワーク できます!
71.
具体例3:AB テストフレームワーク ● 各テストごとにユニークな
Salt を持つ ● ユーザのユニークキー×Salt のハッシュを計算 する ● ハッシュ値を 100 で割ったあまりをとる ● 0~49 → グループA、50~99 → グループB hash(unique_key XOR test_salt) % 100 ※だいたいの概念。本当はもうちっと複雑。
72.
具体例3:AB テストフレームワーク ● 十分に
“良い” ハッシュ関数があれば ○ ユーザのユニークキーが決定した瞬間に、ユーザのグ ループは潜在的に決定済み ○ グループの振り分けは十分にランダム ○ 振り分けの計算は常に O(1) ○ Salt が変わればグループ分けに相関なし ○ あえて Salt を同じにすることで、異なるテストのグルー プ分けをあえて同じにすることもできる ○ グループ分けの割合を変更した場合も、なんら再計算の 必要が無い いいことづくめ!
73.
具体例3:AB テストフレームワーク 難しい問題を シンプルに解く
74.
具体例3:AB テストフレームワーク ちなみに
75.
具体例3:AB テストフレームワーク ● このフレームワーク ●
Proctor という名前でオープンソース化済み http://indeedeng.github.io/proctor/ ● AB テスト結果の分析に適したツールも ● Imhotep という名前で同じくオープンソース化済 み http://indeedeng.github.io/imhotep/
76.
結 論
77.
エンジニアにとっての Indeed 取り組むべき 課題が いっぱい
78.
エンジニアにとっての Indeed コードで解決
79.
エンジニアにとっての Indeed データで証明
80.
エンジニアにとっての Indeed めっちゃ 楽しい
81.
Q & A ※
#askindeed で Twitter 検索すると質疑応答のおおよそが見れます
Download