summaryrefslogtreecommitdiffstats
path: root/toolkit/components/processtools/tests/xpcshell/test_total_cpu_time.js
blob: 00f1ea2b6c1c305e36da9c4c3c6c19e1da6e48b9 (plain)
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
"use strict";

var cpuThreadCount;

add_task(async function setup() {
  // FOG needs a profile directory to put its data in.
  do_get_profile();

  Services.fog.initializeFOG();

  cpuThreadCount = (await Services.sysinfo.processInfo).count;
});

async function getCpuTimeFromProcInfo() {
  const NS_PER_MS = 1000000;
  let cpuTimeForProcess = p => p.cpuTime / NS_PER_MS;
  let procInfo = await ChromeUtils.requestProcInfo();
  return (
    cpuTimeForProcess(procInfo) +
    procInfo.children.map(cpuTimeForProcess).reduce((a, b) => a + b, 0)
  );
}

add_task(async function test_totalCpuTime_in_parent() {
  let startTime = Date.now();

  let initialProcInfoCpuTime = Math.floor(await getCpuTimeFromProcInfo());
  await Services.fog.testFlushAllChildren();

  let initialCpuTime = Glean.power.totalCpuTimeMs.testGetValue();
  Assert.greater(
    initialCpuTime,
    0,
    "The CPU time used by starting the test harness should be more than 0"
  );
  let initialProcInfoCpuTime2 = Math.ceil(await getCpuTimeFromProcInfo());

  Assert.greaterOrEqual(
    initialCpuTime,
    initialProcInfoCpuTime,
    "The CPU time reported through Glean should be at least as much as the CPU time reported by ProcInfo before asking Glean for the data"
  );
  Assert.lessOrEqual(
    initialCpuTime,
    initialProcInfoCpuTime2,
    "The CPU time reported through Glean should be no more than the CPU time reported by ProcInfo after asking Glean for the data"
  );

  // 50 is an arbitrary value, but the resolution is 16ms on Windows,
  // so this needs to be significantly more than 16.
  const kBusyWaitForMs = 50;
  while (Date.now() - startTime < kBusyWaitForMs) {
    // Burn CPU time...
  }

  let additionalProcInfoCpuTime =
    Math.floor(await getCpuTimeFromProcInfo()) - initialProcInfoCpuTime2;
  await Services.fog.testFlushAllChildren();

  let additionalCpuTime =
    Glean.power.totalCpuTimeMs.testGetValue() - initialCpuTime;
  info(
    `additional CPU time according to ProcInfo: ${additionalProcInfoCpuTime}ms and Glean ${additionalCpuTime}ms`
  );

  // On a machine where the CPU is very busy, our busy wait loop might burn less
  // CPU than expected if other processes are being scheduled instead of us.
  let expectedAdditionalCpuTime = Math.min(
    additionalProcInfoCpuTime,
    kBusyWaitForMs
  );
  Assert.greaterOrEqual(
    additionalCpuTime,
    expectedAdditionalCpuTime,
    `The total CPU time should have increased by at least ${expectedAdditionalCpuTime}ms`
  );
  let wallClockTime = Date.now() - startTime;
  Assert.lessOrEqual(
    additionalCpuTime,
    wallClockTime * cpuThreadCount,
    `The total CPU time should have increased by at most the wall clock time (${wallClockTime}ms) * ${cpuThreadCount} CPU threads`
  );
});

add_task(async function test_totalCpuTime_in_child() {
  const MESSAGE_CHILD_TEST_DONE = "ChildTest:Done";

  let startTime = Date.now();
  await Services.fog.testFlushAllChildren();
  let initialCpuTime = Glean.power.totalCpuTimeMs.testGetValue();

  let initialProcInfoCpuTime = await getCpuTimeFromProcInfo();
  run_test_in_child("test_total_cpu_time_child.js");
  let burntCpuTime = await do_await_remote_message(MESSAGE_CHILD_TEST_DONE);
  let additionalProcInfoCpuTime =
    (await getCpuTimeFromProcInfo()) - initialProcInfoCpuTime;

  await Services.fog.testFlushAllChildren();
  let additionalCpuTime =
    Glean.power.totalCpuTimeMs.testGetValue() - initialCpuTime;
  info(
    `additional CPU time according to ProcInfo: ${additionalProcInfoCpuTime}ms and Glean ${additionalCpuTime}ms`
  );

  // On a machine where the CPU is very busy, our busy wait loop might burn less
  // CPU than expected if other processes are being scheduled instead of us.
  let expectedAdditionalCpuTime = Math.min(
    Math.floor(additionalProcInfoCpuTime),
    burntCpuTime
  );
  Assert.greaterOrEqual(
    additionalCpuTime,
    expectedAdditionalCpuTime,
    `The total CPU time should have increased by at least ${expectedAdditionalCpuTime}ms`
  );
  let wallClockTime = Date.now() - startTime;
  Assert.lessOrEqual(
    additionalCpuTime,
    wallClockTime * cpuThreadCount,
    `The total CPU time should have increased by at most the wall clock time (${wallClockTime}ms) * ${cpuThreadCount} CPU threads`
  );
});