Home Reference Source

src/performance/performance-monitor.ts

/*
 * Push the performance monitor as the last core component in hls.ts
 * so that it is the last class to handle events.
 *
 * coreComponents.push(new PerformanceMonitor(this));
 *
 * TODO: Add this to the demo page or a performance test page
 */

import { Events } from '../events';
import { logger } from '../utils/logger';
import Hls from '../hls';
import type { FragBufferedData } from '../types/events';

export default class PerformanceMonitor {
  private hls: Hls;

  constructor(hls: Hls) {
    this.hls = hls;
    this.hls.on(Events.FRAG_BUFFERED, this.onFragBuffered);
  }

  destroy() {
    this.hls.off(Events.FRAG_BUFFERED);
  }

  onFragBuffered(event: Events.FRAG_BUFFERED, data: FragBufferedData) {
    logFragStats(data);
  }
}

function logFragStats(data: FragBufferedData) {
  const { frag, part } = data;
  const stats = part ? part.stats : frag.stats;
  const tLoad = stats.loading.end - stats.loading.start;
  const tBuffer = stats.buffering.end - stats.buffering.start;
  const tParse = stats.parsing.end - stats.parsing.start;
  const tTotal = stats.buffering.end - stats.loading.start;

  logger.log(`[performance-monitor]: Stats for fragment ${frag.sn} ${
    part ? ' part ' + part.index : ''
  } of level ${frag.level}:
        Size:                       ${(stats.total / 1024).toFixed(3)} kB
        Chunk Count:                ${stats.chunkCount}

        Request:                    ${stats.loading.start.toFixed(3)} ms
        First Byte:                 ${stats.loading.first.toFixed(3)} ms
        Parse Start                 ${stats.parsing.start.toFixed(3)} ms
        Buffering Start:            ${stats.buffering.start.toFixed(3)} ms
        First Buffer:               ${stats.buffering.first.toFixed(3)} ms
        Parse End:                  ${stats.parsing.end.toFixed(3)} ms
        Buffering End:              ${stats.buffering.end.toFixed(3)} ms

        Load Duration:              ${tLoad.toFixed(3)} ms
        Parse Duration:             ${tParse.toFixed(3)} ms
        Buffer Duration:            ${tBuffer.toFixed(3)} ms
        End-To-End Duration:        ${tTotal.toFixed(3)} ms`);
}