summaryrefslogtreecommitdiff
path: root/src/parser/Stats.ts
blob: 5f7f991f82ed317a9a18ad836508a1d948e8b66c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// @ts-nocheck

const now =
  typeof process !== 'undefined' && process.hrtime
    ? () => {
        const t = process.hrtime();
        return t[0] * 1e3 + t[1] / 1e6;
      }
    : () => self.performance.now();

interface Timing {
  label: string;
  start: number;
  end: number;
  children: Timing[];
}

/** Format benchmarks */
function collapse_timings(timings) {
  const result = {};
  timings.forEach((timing) => {
    result[timing.label] = Object.assign(
      {
        total: timing.end - timing.start,
      },
      timing.children && collapse_timings(timing.children)
    );
  });
  return result;
}

export default class Stats {
  start_time: number;
  current_timing: Timing;
  current_children: Timing[];
  timings: Timing[];
  stack: Timing[];

  constructor() {
    this.start_time = now();
    this.stack = [];
    this.current_children = this.timings = [];
  }

  start(label) {
    const timing = {
      label,
      start: now(),
      end: null,
      children: [],
    };

    this.current_children.push(timing);
    this.stack.push(timing);

    this.current_timing = timing;
    this.current_children = timing.children;
  }

  stop(label) {
    if (label !== this.current_timing.label) {
      throw new Error(`Mismatched timing labels (expected ${this.current_timing.label}, got ${label})`);
    }

    this.current_timing.end = now();
    this.stack.pop();
    this.current_timing = this.stack[this.stack.length - 1];
    this.current_children = this.current_timing ? this.current_timing.children : this.timings;
  }

  render() {
    const timings = Object.assign(
      {
        total: now() - this.start_time,
      },
      collapse_timings(this.timings)
    );

    return {
      timings,
    };
  }
}