Профилирование приложения

Профилирование помогает понять реальное влияние timeago.js на производительность приложения и выявить узкие места.


Инструменты профилирования

Инструмент Применение
Chrome Performance Таймеры, reflow, CPU-нагрузка
Chrome Memory Heap snapshot, утечки памяти
Chrome Coverage Неиспользуемый JavaScript
Lighthouse Комплексная оценка производительности
Web Vitals (CWV) INP, CLS, LCP
performance.now() Точное время выполнения кода

Профилирование в Chrome Performance

Шаги:

  1. Открыть DevTools (F12) → вкладка Performance.
  2. Нажать кнопку Record (кружок).
  3. Подождать 30–60 секунд с активным приложением.
  4. Нажать Stop.

Что искать:

  • В строке Main — “Timer Fired” (таймеры timeago).
  • В блоке Timings — время на reflow/layout.
  • В Summary — процент Scripting и Rendering.

Подсчёт активных таймеров

// Инструмент диагностики
let renderCount  = 0;
let cancelCount  = 0;
let activeTimers = 0;

const originalRender = import('timeago.js').then(m => m.render);
const originalCancel = import('timeago.js').then(m => m.cancel);

// Обёртки для подсчёта
window.__timeagoStats = {
  get active() { return activeTimers; },
  get renders() { return renderCount; },
  get cancels() { return cancelCount; },
};

Замер времени форматирования

import { format } from 'timeago.js';

function benchmarkFormat(iterations = 10000) {
  const dates = Array.from({ length: iterations }, (_, i) =>
    Date.now() - i * 1000
  );

  const start = performance.now();

  dates.forEach(d => format(d, 'ru'));

  const elapsed = performance.now() - start;

  console.log(`${iterations} вызовов format: ${elapsed.toFixed(2)}ms`);
  console.log(`Среднее: ${(elapsed / iterations).toFixed(4)}ms на вызов`);
}

benchmarkFormat();

Анализ утечек памяти

Процедура:

  1. DevTools → Memory → Heap snapshot → “Take snapshot”.
  2. Выполнить несколько циклов монтирования/размонтирования компонентов.
  3. “Take snapshot” снова.
  4. Выбрать режим Comparison.
  5. Искать HTMLTimeElement с положительным “# New”.

Если количество HTMLTimeElement растёт — cancel вызывается некорректно.


Мониторинг CLS (Cumulative Layout Shift)

timeago.js меняет textContent, что может вызвать CLS если:

  • элемент не имеет фиксированного размера;
  • текст при обновлении увеличивается в размере.

Замер CLS:

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (entry.hadRecentInput) continue;
    console.log('CLS entry:', entry.value);
  }
});

observer.observe({ type: 'layout-shift', buffered: true });

Предотвращение:

time.time-ago {
  min-width: 10ch;
  display: inline-block;
}

Количество DOM-операций в секунду

import { format } from 'timeago.js';

let updateCount = 0;
const startTime = performance.now();

setInterval(() => {
  document.querySelectorAll('[datetime]').forEach(el => {
    const prev = el.textContent;
    const next = format(el.getAttribute('datetime'), 'ru');
    if (prev !== next) {
      el.textContent = next;
      updateCount++;
    }
  });

  const elapsed = (performance.now() - startTime) / 1000;
  console.log(`DOM updates/sec: ${(updateCount / elapsed).toFixed(1)}`);
}, 5000);

Web Workers для мониторинга

// monitor-worker.js
let elements = [];
let lastStats = {};

setInterval(() => {
  const now = Date.now();
  const stats = {
    timestamp: now,
    elementCount: elements.length,
  };
  self.postMessage(stats);
}, 5000);

Lighthouse для сводной оценки

npx lighthouse https://your-site.com --view

Проверять:

  • Total Blocking Time (TBT) — если таймеры блокируют основной поток.
  • Largest Contentful Paint (LCP) — не должно ухудшаться от timeago.
  • Time to Interactive (TTI) — инициализация render не должна быть в critical path.

Практический чеклист профилирования

  • Запустить Performance Recording на 30 секунд.
  • Убедиться, что Timer Fired вызовы занимают < 1% CPU.
  • Heap Snapshot до и после 5 циклов монтирования: нет роста HTMLTimeElement.
  • CLS = 0 после обновлений текста.
  • Количество активных таймеров не превышает количество видимых элементов.