Skip to content

embedding生成のバッチサイズ拡大による高速化 #135

@Kewton

Description

@Kewton

概要

Ollama embedding APIのバッチサイズを10→50に拡大し、embedding生成を3-5倍高速化する。

背景

現在のembedding生成は58692セクションで約630秒かかる。ボトルネック分析の結果:

ステップ 推定時間 割合 原因
Ollama API呼び出し ~590秒 94% バッチサイズ10 → 5870回のHTTPリクエスト
SQLite書き込み ~20-40秒 3-6% autocommit
テキスト取得 数秒 1% -

対応内容

T1: バッチサイズ拡大

  • ファイル: src/embedding/ollama.rs 行12
  • 変更: const BATCH_SIZE: usize = 10;const BATCH_SIZE: usize = 50;
  • 期待効果: 5870回 → 1174回のリクエストに削減。630秒 → 120-200秒(3-5倍高速化)
  • タイムアウト調整: REQUEST_TIMEOUT_SECS(現在30秒、行18)を60秒に引き上げる。バッチサイズ拡大でリクエスト処理時間が増加するためマージンを確保。

T2: SQLiteトランザクションバッチ化

  • ファイル: src/embedding/store.rs, src/cli/embed.rssections.iter().zip(embeddings.iter()) のループ内 upsert_embedding 呼び出し), src/cli/index.rsgenerate_embeddings_for_manifest() 内の同様のupsertループ。incremental更新経路も含む)
  • 変更内容:
    1. EmbeddingStoreexecute_in_transaction<F, T>(&self, f: F) -> Result<T> メソッドを新設。内部で self.conn.execute_batch("BEGIN") / self.conn.execute_batch("COMMIT") を使用(rusqliteの &self 制約に適合する raw SQL 方式)。
    2. embed.rs のファイル単位ループ(行150 for entry in &manifest.files)内でトランザクションを適用。
    3. index.rsgenerate_embeddings_for_manifest() 内の同様のupsertループにも同じトランザクションを適用(incremental更新経路含む)。
  • トランザクションスコープ: ファイル単位(= そのファイルの全セクション)。
  • API契約: execute_in_transaction はクロージャが Ok を返した場合のみ COMMITErr を返した場合は ROLLBACK を実行。これにより has_current_embedding() のキャッシュ判定(パス+ハッシュでファイル全体の処理済み判定)と整合する。一部sectionが失敗した場合はファイル全体をROLLBACKし、再実行時に自動回復可能にする。
  • エラー時振る舞いの変更: 現行コードではsection単位でエラースキップ・次セクション続行だが、T2導入後はファイル単位でROLLBACK・次ファイル続行に変わる。失敗したファイルは再実行時に自動回復される。
  • 期待効果: 58692回の個別fsync → ファイル数(2909)回に削減。20-40秒の削減
  • 備考: T2はプロバイダー非依存の改善であり、OpenAI利用時にも同様の効果がある。

影響範囲

変更対象ファイル

ファイル 変更内容 影響度
src/embedding/ollama.rs BATCH_SIZE, REQUEST_TIMEOUT_SECS 定数変更 低(内部定数のみ)
src/embedding/store.rs execute_in_transaction() メソッド追加 中(新API追加)
src/cli/embed.rs upsertループをトランザクションで囲む
src/cli/index.rs generate_embeddings_for_manifest() のupsertループをトランザクションで囲む(incremental更新含む)

影響を受けないファイル

  • src/search/ - 読み取り専用のため影響なし(※埋め込み再生成後の回帰確認推奨)
  • src/cli/suggest.rs - 読み取り専用のため影響なし
  • src/cli/status/ - 読み取り専用のため影響なし
  • src/embedding/openai.rs - BATCH_SIZE=100は変更なし

パフォーマンス影響

  • 正常系: API呼び出し回数5分の1削減、SQLite fsync回数大幅削減。3-5倍の高速化期待。
  • 異常系: REQUEST_TIMEOUT_SECS=60により、Ollama停止時の1リクエストあたり待機時間が30秒→60秒に。ファイル単位ROLLBACKにより失敗時は同ファイルの全セクションを再処理。

外部コンポーネントへの影響

  • Ollama: 1リクエストあたりの入力テキスト量が5倍に増加。VRAM使用量増加。
  • SQLite: トランザクション時間が長くなる代わりにfsync回数が大幅削減。Rust crateの追加・更新は不要。

リスク

  • バッチサイズ拡大によりOllamaのVRAM使用量が増加。50で問題がある場合は30に下げる
  • OpenAIプロバイダーは既にBATCH_SIZE=100で問題なし

受け入れ基準

  • BATCH_SIZE=50 に変更後、cargo test --all が全パスすること
  • cargo clippy --all-targets -- -D warnings で警告0件
  • cargo fmt --all -- --check で差分なし
  • EmbeddingStoreexecute_in_transaction メソッドが追加され、embed.rsindex.rs の両方から利用されていること
  • execute_in_transaction のcommit/rollback動作の単体テストが追加されていること
  • REQUEST_TIMEOUT_SECS がバッチサイズ拡大に合わせて調整されていること
  • 手動テスト: embed コマンド実行時にエラーなく完了すること
  • 手動テスト: index --with-embedding コマンド実行時にエラーなく完了すること

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions