👋

【GENIEE1dayインターン体験記】DSP広告配信システムの爆速化に挑んだ話

に公開

はじめに

2025年7月、株式会社ジーニーのエンジニア向け 1day インターンに参加しました!

当日は 「広告配信システム(DSP)の高速化」 という実務さながらのテーマに挑戦。
本記事では、私が実装した高速化手法・技術的工夫・学びをまとめます。


高速化施策まとめ

  • N+1 問題 → 一括取得化
  • キャッシュ導入 → DB アクセス削減
  • 並列処理(thread / process) → レスポンス改善
  • GIL 対策 → プロセスベース+プリフォーク

🏢 ジーニー社について

  • 広告 SaaS を軸に、AI やマーケティング領域へ事業展開
  • 生成 AI 検索エンジン「AI SEARCH」を開発
  • エンジニアの3割が競技プログラミング出身で実装力が高い
  • フルスタック × AI が学べる環境

👉 詳しくは 公式 note をチェック!


インターン概要

項目 内容
開催形式 オフライン(新宿オークタワー本社)
使用技術 Python 3.12 / MySQL / Prometheus / Grafana / Docker
テーマ 広告配信処理の高速化チューニング

社内の雰囲気

IMG_3411.jpg
IMG_3415.jpg

開放的な環境でインターンを実施しました!


課題:DSP 広告配信の最適化

処理フロー(要約)

  1. サイズ一致フィルタ
  2. ドメインブロック
  3. カテゴリ制御
  4. 特徴量ターゲティング
  5. 価格最大広告の選定

評価条件(例:medium)

項目
広告主数 300–450
リクエスト数 100
制限時間 5 秒

実装した高速化施策

1. N+1 問題の解消

# ループ内での fetch → 一括取得に変更
advertisers = fetchAllAdvertisers()
advertiser_map = {adv.id: adv for adv in advertisers}

DB アクセスを O(n) → O(1) に削減!


2. TTL キャッシュの導入

class DataCache:
    def __init__(self, ttl_sec: int = 300):
        self.cache = {}
        self.ttl = ttl_sec

頻繁に変わらないデータは再取得せず即レスポンス!


3. 並列処理(スレッド+条件分岐)

# 特徴量マッチングを並列化
if len(ads_list) > 100:
    with ThreadPoolExecutor() as pool:
        result = list(pool.map(targeting_func, ads_list))

データサイズに応じて並列化 / 逐次処理を自動切替


4. GIL 回避のためプロセスベースへ

• multiprocessing で真の並列化
• プリフォーク方式で起動時にワーカー生成
• ThreadingHTTPServer → ForkingHTTPServer へ変更

start_time = time.time()
server.prefork_workers()  # 事前にワーカーを生成
time.sleep(2)

5. 可視化(Prometheus + Grafana)

curl http://localhost:8888/metrics

• auction_requests_total などのメトリクスを公開
• Grafana ダッシュボードでパフォーマンスを確認!


学び・感想

• 処理順とメトリクス設計が最適化のカギ
• GIL / fork など Python 内部構造の理解がパフォーマンスに直結
• 広告配信の舞台裏で「誰より速く、誰より正確に届ける」面白さを体感


最後に

ジーニーのインターンでは、本番に近い負荷要件下で自分の技術を試せました。
ありがとうございました!


補足リンク

Discussion