Skip to content

JavaScriptレンダリング最適化 - Phase 4: 並列処理最適化 #73

@aoshimash

Description

@aoshimash

⚡ JavaScriptレンダリング最適化 - Phase 4: 並列処理最適化

概要

JavaScriptレンダリングの並列処理を最適化し、複数ページの同時レンダリングを効率的に行えるようにします。

前提条件

実装内容

1. JSレンダリング専用ワーカープール

// internal/crawler/js_worker.go
type JSRenderWorker struct {
    id       int
    browser  playwright.Browser
    taskChan <-chan RenderTask
    results  chan<- RenderResult
    logger   *slog.Logger
}

type RenderTask struct {
    URL      string
    Context  context.Context
}

type RenderResult struct {
    URL      string
    HTML     string
    Error    error
    WorkerID int
    Duration time.Duration
}

2. 並列度の動的制御

// internal/crawler/js_coordinator.go
type JSCoordinator struct {
    pool        *BrowserPool
    workers     []*JSRenderWorker
    taskQueue   chan RenderTask
    results     chan RenderResult
    concurrency int
    logger      *slog.Logger
}

func (c *JSCoordinator) AdjustConcurrency(memoryUsage float64) {
    if memoryUsage > 80 {
        c.reduceConcurrency()
    } else if memoryUsage < 50 {
        c.increaseConcurrency()
    }
}

3. バッチ処理の最適化

// 同一ドメインのURLをバッチ化
func (c *JSCoordinator) BatchByDomain(urls []string) map[string][]string {
    batches := make(map[string][]string)
    for _, url := range urls {
        domain := extractDomain(url)
        batches[domain] = append(batches[domain], url)
    }
    return batches
}

// ドメインごとに同じブラウザコンテキストを使用
func (w *JSRenderWorker) ProcessBatch(domain string, urls []string) []RenderResult {
    context, _ := w.browser.NewContext()
    defer context.Close()
    
    results := make([]RenderResult, 0, len(urls))
    for _, url := range urls {
        result := w.renderWithContext(context, url)
        results = append(results, result)
    }
    return results
}

4. リソース制限とモニタリング

// メモリ使用量の監視
func (c *JSCoordinator) MonitorResources() {
    ticker := time.NewTicker(10 * time.Second)
    defer ticker.Stop()
    
    for range ticker.C {
        var m runtime.MemStats
        runtime.ReadMemStats(&m)
        
        memoryUsagePercent := float64(m.Alloc) / float64(m.Sys) * 100
        c.AdjustConcurrency(memoryUsagePercent)
        
        c.logger.Info("Resource usage",
            "memory_mb", m.Alloc/1024/1024,
            "goroutines", runtime.NumGoroutine(),
            "workers", len(c.workers))
    }
}

設定オプション

--js-workers 3           # 並列ワーカー数(デフォルト: CPU数/2)
--js-batch-size 10       # バッチサイズ(デフォルト: 10)
--js-queue-size 100      # タスクキューサイズ(デフォルト: 100)
--js-adaptive            # 動的並列度調整を有効化

テスト項目

  • 並列レンダリングの動作確認
  • メモリ使用量の制限確認
  • 動的並列度調整の動作
  • エラー時のリカバリー

成功基準

  • 10ページの並列レンダリングが単体の3倍以内の時間で完了
  • メモリ使用量が設定した制限内に収まる
  • CPU使用率が適切にスケールする

注意事項

  • Playwrightのブラウザインスタンスは重いため、並列度は控えめに
  • メモリ不足によるクラッシュを防ぐため、動的制御は必須

関連Issue

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions