💾 JavaScriptレンダリング最適化 - Phase 3: キャッシュ機能
概要
レンダリング結果をキャッシュすることで、同じページへの再アクセス時のパフォーマンスを大幅に向上させます。
前提条件
実装内容
1. シンプルなインメモリキャッシュ
// internal/cache/render_cache.go
type RenderCache struct {
cache sync.Map // URLをキー、CacheEntryを値とする
ttl time.Duration
maxSize int
currentSize int32
}
type CacheEntry struct {
HTML string
Timestamp time.Time
}
func NewRenderCache(ttl time.Duration, maxSize int) *RenderCache {
return &RenderCache{
ttl: ttl,
maxSize: maxSize,
}
}
2. キャッシュ操作
func (rc *RenderCache) Get(url string) (string, bool) {
value, ok := rc.cache.Load(url)
if !ok {
return "", false
}
entry := value.(*CacheEntry)
if time.Since(entry.Timestamp) > rc.ttl {
rc.cache.Delete(url)
atomic.AddInt32(&rc.currentSize, -1)
return "", false
}
return entry.HTML, true
}
func (rc *RenderCache) Set(url, html string) {
// サイズチェック(簡易版)
if int(atomic.LoadInt32(&rc.currentSize)) >= rc.maxSize {
rc.evictOldest()
}
rc.cache.Store(url, &CacheEntry{
HTML: html,
Timestamp: time.Now(),
})
atomic.AddInt32(&rc.currentSize, 1)
}
3. JSクライアントへの統合
// internal/client/js_client.go の修正
func (c *JSClient) Get(ctx context.Context, url string) (Response, error) {
// キャッシュチェック
if c.cache != nil {
if html, ok := c.cache.Get(url); ok {
c.logger.Debug("Cache hit", "url", url)
return &JSResponse{
body: html,
statusCode: 200,
fromCache: true,
}, nil
}
}
// 通常のレンダリング処理
resp, err := c.renderWithBrowser(ctx, url)
if err == nil && c.cache != nil {
c.cache.Set(url, resp.String())
}
return resp, err
}
設定オプション
--js-cache # キャッシュ有効化
--js-cache-size 100 # 最大キャッシュエントリ数(デフォルト: 100)
--js-cache-ttl 5m # キャッシュ有効期限(デフォルト: 5分)
テスト項目
成功基準
- キャッシュヒット時のレスポンスが100ms以下
- メモリ使用量が予測可能で安定している
- キャッシュヒット率の統計が取得できる
関連Issue
💾 JavaScriptレンダリング最適化 - Phase 3: キャッシュ機能
概要
レンダリング結果をキャッシュすることで、同じページへの再アクセス時のパフォーマンスを大幅に向上させます。
前提条件
実装内容
1. シンプルなインメモリキャッシュ
2. キャッシュ操作
3. JSクライアントへの統合
設定オプション
テスト項目
成功基準
関連Issue