---
sidebar_label: "Повторное использование Processor и кэш"
title: "Processor и кэш - CyberGo html | производительность"
description: "Переиспользование Processor и кэш CyberGo html: отличие от функций пакета, sync.Pool, стратегия кэша и мониторинг hit-rate для производительности."
sidebar_position: 1
---

# Повторное использование Processor и кэш

Это руководство объясняет различия между функциями уровня пакета и экземплярами Processor, помогая сделать правильный выбор и добиться оптимальной производительности в различных сценариях.

## Два режима вызова

### Функции уровня пакета (однократный вызов)

```go
result, err := html.Extract(data)
```

Внутренне использует `sync.Pool` для управления временными Processor: при каждом вызове Processor извлекается из пула, а после использования возвращается обратно.

**Применимые сценарии**: редкие вызовы (например, CLI-утилиты, одноразовые скрипты)

**Жизненный цикл**:

```text
Вызов Extract()
  → Получение Processor из sync.Pool (или создание нового)
  → Выполнение извлечения
  → Возврат в sync.Pool
```

### Экземпляр Processor (режим повторного использования)

```go
p, _ := html.New()
defer p.Close()

for _, page := range pages {
    result, _ := p.Extract(page)
}
```

Создаётся независимый экземпляр Processor с ручным управлением жизненным циклом.

**Применимые сценарии**: высокочастотные вызовы (например, веб-сервисы, сканеры)

**Жизненный цикл**:

```text
html.New()
  → Создание Processor (кэш, аудит, статистика)
  → Циклический вызов p.Extract() (повторное использование кэша)
  → defer p.Close()
```

## Как выбрать

| Сценарий | Рекомендуемый способ | Причина |
|------|----------|------|
| CLI-утилиты, однократная обработка | Функции пакета | Просто и прямолинейно, не требует управления |
| Веб-сервисы, API-бэкенд | Экземпляр Processor | Ускорение через кэш, мониторинг статистики |
| Пакетные сканеры | Экземпляр Processor | Дедупликация через кэш, контролируемые ресурсы |
| Тестовый код | Функции пакета | Без сохранения состояния, изоляция тестов |

## Механизм кэширования

Экземпляр Processor имеет встроенный кэш на основе контента. Одинаковый HTML-ввод не обрабатывается повторно.

### Настройка кэша

```go
cfg := html.DefaultConfig()
cfg.MaxCacheEntries = 2000     // Максимальное количество записей в кэше (0=отключить)
cfg.CacheTTL = time.Hour       // Время жизни записей кэша
cfg.CacheCleanup = 5 * time.Minute // Интервал фоновой очистки
```

| Параметр | По умолчанию | Описание |
|------|--------|------|
| `MaxCacheEntries` | 2000 | Максимальная ёмкость кэша, установка в 0 отключает кэш |
| `CacheTTL` | 1 час | Время жизни записей |
| `CacheCleanup` | 5 минут | Интервал фоновой очистки устаревших записей |

### Генерация ключа кэша

Ключ кэша генерируется на основе контента после конвертации в UTF-8:
- Для контента менее 64 КБ: хеш вычисляется от полного содержимого
- Для контента более 64 КБ: используется алгоритм 5-точечной выборки (начало + конец + равномерная выборка)

Одинаковый HTML-контент при повторных вызовах попадает в кэш напрямую, минуя этапы парсинга и извлечения.

## Мониторинг попаданий в кэш

```go
p, _ := html.New()
defer p.Close()

// Обработка пакета страниц
for _, page := range pages {
    p.Extract(page)
}

// Получение статистики
stats := p.GetStatistics()
fmt.Printf("Всего обработано: %d\n", stats.TotalProcessed)
fmt.Printf("Попаданий в кэш: %d\n", stats.CacheHits)
fmt.Printf("Промахов кэша: %d\n", stats.CacheMisses)

hitRate := float64(stats.CacheHits) / float64(stats.TotalProcessed) * 100
fmt.Printf("Процент попаданий: %.1f%%\n", hitRate)
```

## Рекомендуемые паттерны

### Singleton веб-сервиса

В веб-сервисах рекомендуется использовать Singleton Processor:

```go
var processor *html.Processor

func init() {
    cfg := html.DefaultConfig()
    cfg.MaxCacheEntries = 5000
    cfg.CacheTTL = 30 * time.Minute
    cfg.ProcessingTimeout = 10 * time.Second

    var err error
    processor, err = html.New(cfg)
    if err != nil {
        log.Fatal(err)
    }
}

func handleExtract(w http.ResponseWriter, r *http.Request) {
    data, _ := io.ReadAll(r.Body)
    result, err := processor.Extract(data)
    if err != nil {
        http.Error(w, err.Error(), 500)
        return
    }
    json.NewEncoder(w).Encode(result)
}
```

### Пакетная обработка сканера

```go
p, _ := html.New(html.DefaultConfig())
defer p.Close()

urls := crawlURLs()
pages := fetchPages(urls) // [][]byte

batch := p.ExtractBatch(pages)
fmt.Printf("Успешно: %d, Неудачно: %d\n", batch.Success, batch.Failed)
```

### Регулярное обслуживание

Долго работающий Processor требует регулярного обслуживания:

```go
// Регулярная очистка кэша (предотвращение роста памяти)
go func() {
    ticker := time.NewTicker(10 * time.Minute)
    for range ticker.C {
        p.ClearCache()
    }
}()

// Регулярный сброс статистики (с сохранением кэша)
go func() {
    ticker := time.NewTicker(time.Hour)
    for range ticker.C {
        stats := p.GetStatistics()
        log.Printf("Обработано %d раз, ошибок %d",
            stats.TotalProcessed, stats.ErrorCount)
        p.ResetStatistics()
    }
}()
```

## Сравнение производительности

Повторная обработка одного и того же HTML 1000 раз (для справки):

| Режим | Первая обработка | Попадание в кэш |
|------|----------|----------|
| Функции пакета | Базовый | Нет кэша |
| Processor (без кэша) | ≈Базовый | ≈Базовый |
| Processor (с кэшем) | ≈Базовый | ≈1/10 от базового |

:::tip Условия действия кэша
Кэш работает только на экземпляре Processor. Функции уровня пакета переиспользуют Processor через `sync.Pool`, но конфигурация пула отключает кэш (`MaxCacheEntries = 0`) и очищает кэш при возврате, поэтому кэширование недоступно.
:::

## Частые заблуждения

| Заблуждение | Правильный подход |
|------|----------|
| Создание Processor через `html.New()` при каждом вызове | Повторное использование одного экземпляра |
| Забыли вызвать `p.Close()` | Используйте `defer p.Close()` |
| Ожидание кэша от функций уровня пакета | Кэш работает только на экземплярах Processor |
| Использование Processor после закрытия | Проверяйте ошибку `ErrProcessorClosed` |

## Следующие шаги

- [Оптимизация производительности](../../advanced/performance) - Дополнительные советы по оптимизации
- [Справочник API: Processor](../../api-reference/core/processor) - Полный список методов
- [Справочник API: Конфигурация](../../api-reference/core/config) - Подробности настройки кэша
