summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Hanzel <mhanzel@gitlab.com>2019-06-05 09:14:36 +0200
committerMartin Hanzel <mhanzel@gitlab.com>2019-06-05 09:14:36 +0200
commit01bf2c41efa9b3bafb77aa2bc38cdc8e669c1b45 (patch)
tree29bb17ead16c7e49bc6887b9fff60f8bdab1e115
parent5d618ead71d4ee9bb54926f764a77a9d90b9912b (diff)
downloadgitlab-ce-mh/cpu-time.tar.gz
Add getrusage packagemh/cpu-time
-rw-r--r--package.json1
-rw-r--r--spec/frontend/helpers/cpu_time.js33
-rw-r--r--spec/frontend/helpers/cpu_time_spec.js72
-rw-r--r--spec/frontend/helpers/timeout.js32
-rw-r--r--yarn.lock22
5 files changed, 38 insertions, 122 deletions
diff --git a/package.json b/package.json
index 0cbc178a923..b48751a1188 100644
--- a/package.json
+++ b/package.json
@@ -161,6 +161,7 @@
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jasmine": "^2.10.1",
"eslint-plugin-jest": "^22.3.0",
+ "getrusage": "^1.0.0",
"gettext-extractor": "^3.4.3",
"gettext-extractor-vue": "^4.0.2",
"graphql-tag": "^2.10.0",
diff --git a/spec/frontend/helpers/cpu_time.js b/spec/frontend/helpers/cpu_time.js
deleted file mode 100644
index 77a70519b1b..00000000000
--- a/spec/frontend/helpers/cpu_time.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import subprocess from 'child_process';
-import os from 'os';
-import process from 'process';
-
-const getSeconds = str => {
- const parts = str.trim().split(/[:.]/).map(val => Number(val)); // [minutes, seconds, hundredths]
- return parts[0] * 60 + parts[1] + parts[2] / 100;
-};
-
-/**
- * On *nix systems, tries to get the elapsed CPU time (user and kernelspace), in seconds, of the current process. This is achieved via the `ps` command. Some nice day in the future, this may be implemented using a C extension and the `clock` posix function.
- *
- * On Windows, and wherever the `ps` command fails, returns the current process uptime, in seconds.
- */
-// eslint-disable-next-line import/prefer-default-export
-export const cpuTime = () => {
- // Node doesn't have a facility for getting the CPU time of its own process, so we must get it
- // from the `ps` command. Sadly, Linux and BSD `ps` are different, so we must handle each case.
- // Windows is not implemented at the moment.
- const platform = os.platform();
- try {
- if (platform === 'win32') {
- // Let's not support windows now
- return { time: process.uptime(), cpu: false };
- }
-
- const out = subprocess.execSync(`ps -p ${process.pid} -o time=`, { encoding: 'utf-8' });
- return { time: getSeconds(out), cpu: true };
- } catch (e) {
- // ps command failed
- return { time: process.uptime(), cpu: false };
- }
-};
diff --git a/spec/frontend/helpers/cpu_time_spec.js b/spec/frontend/helpers/cpu_time_spec.js
deleted file mode 100644
index 400eed2872d..00000000000
--- a/spec/frontend/helpers/cpu_time_spec.js
+++ /dev/null
@@ -1,72 +0,0 @@
-import crypto from 'crypto';
-import os from 'os';
-import process from 'process';
-
-import { setTestTimeoutOnce } from 'helpers/timeout';
-import { cpuTime } from './cpu_time';
-
-describe('cpu_time', () => {
- // Swap timers before and after, because our test harness assumes fake timers in after hooks and
- // will complain if real timers are set.
- beforeEach(() => {
- jest.useRealTimers();
- });
-
- afterEach(() => {
- jest.useFakeTimers();
- });
-
- it('measures CPU time less than real time in async code', done => {
- if (os.platform === 'win32') {
- done();
- }
-
- setTestTimeoutOnce(2000);
- const cpu1 = cpuTime();
- const real1 = process.uptime();
- expect(cpu1.cpu).toBe(true);
-
- setTimeout(() => {
- const deltaCPU = cpuTime().time - cpu1.time;
- const deltaReal = process.uptime() - real1;
-
- expect(deltaCPU).toBeLessThan(deltaReal);
- expect(deltaCPU).toBeLessThan(0.2); // Shouldn't take more than 200 ms CPU time
- expect(deltaReal).toBeGreaterThan(1);
- done();
- }, 1000);
-
- }, 2000);
-
- it('measures CPU time about the same as real time in sync code', done => {
- if (os.platform === 'win32') {
- done();
- }
-
- setTestTimeoutOnce(5000);
- const cpu1 = cpuTime();
- const real1 = process.uptime();
- expect(cpu1.cpu).toBe(true);
-
- // Do an expensive operation for at least one second
- let str = '';
- let iters = 0;
- while (process.uptime() - real1 <= 1) {
- const hash = crypto.createHash('sha256');
- hash.update(Math.random().toString());
- str += hash.digest('hex');
- iters += 1;
- }
-
- // Make sure that the test actually did do work
- expect(str.length).toBe(256 * iters / 4); // 256 bits * iterations / 4 bits per hex char
-
- const deltaCPU = cpuTime().time - cpu1.time;
- const deltaReal = process.uptime() - real1;
- expect(deltaCPU).toBeLessThan(1);
- expect(deltaCPU).toBeGreaterThan(0.1);
- expect(deltaReal).toBeGreaterThan(deltaCPU);
-
- done();
- }, 5000);
-});
diff --git a/spec/frontend/helpers/timeout.js b/spec/frontend/helpers/timeout.js
index e74598ae20a..30b07bd7011 100644
--- a/spec/frontend/helpers/timeout.js
+++ b/spec/frontend/helpers/timeout.js
@@ -1,46 +1,46 @@
-const NS_PER_SEC = 1e9;
-const NS_PER_MS = 1e6;
+import rusage from 'getrusage';
+
+const MS_PER_S = 1000;
const IS_DEBUGGING = process.execArgv.join(' ').includes('--inspect-brk');
-let testTimeoutNS;
+let testTimeoutMS;
export const setTestTimeout = newTimeoutMS => {
- testTimeoutNS = newTimeoutMS * NS_PER_MS;
+ testTimeoutMS = newTimeoutMS;
jest.setTimeout(newTimeoutMS);
};
// Allows slow tests to set their own timeout.
// Useful for tests with jQuery, which is very slow in big DOMs.
-let temporaryTimeoutNS = null;
+let temporaryTimeoutMS = null;
export const setTestTimeoutOnce = newTimeoutMS => {
- temporaryTimeoutNS = newTimeoutMS * NS_PER_MS;
+ temporaryTimeoutMS = newTimeoutMS;
};
export const initializeTestTimeout = defaultTimeoutMS => {
setTestTimeout(defaultTimeoutMS);
- let testStartTime;
+ let testStartTimeS;
// https://github.com/facebook/jest/issues/6947
beforeEach(() => {
- testStartTime = process.hrtime();
+ testStartTimeS = rusage.getcputime();
});
afterEach(() => {
- let timeoutNS = testTimeoutNS;
- if (Number.isFinite(temporaryTimeoutNS)) {
- timeoutNS = temporaryTimeoutNS;
- temporaryTimeoutNS = null;
+ let timeoutMS = testTimeoutMS;
+ if (Number.isFinite(temporaryTimeoutMS)) {
+ timeoutMS = temporaryTimeoutMS;
+ temporaryTimeoutMS = null;
}
- const [seconds, remainingNs] = process.hrtime(testStartTime);
- const elapsedNS = seconds * NS_PER_SEC + remainingNs;
+ const elapsedMS = (rusage.getcputime() - testStartTimeS) * MS_PER_S;
// Disable the timeout error when debugging. It is meaningless because
// debugging always takes longer than the test timeout.
- if (elapsedNS > timeoutNS && !IS_DEBUGGING) {
+ if (elapsedMS > timeoutMS && !IS_DEBUGGING) {
throw new Error(
- `Test took too long (${elapsedNS / NS_PER_MS}ms > ${timeoutNS / NS_PER_MS}ms)!`,
+ `Test took too long (${elapsedMS}ms > ${timeoutMS}ms)!`,
);
}
});
diff --git a/yarn.lock b/yarn.lock
index 898159975fa..d3b2c008e5c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1733,6 +1733,13 @@ binaryextensions@2:
resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-2.1.1.tgz#3209a51ca4a4ad541a3b8d3d6a6d5b83a2485935"
integrity sha512-XBaoWE9RW8pPdPQNibZsW2zh8TW6gcarXp1FZPwT8Uop8ScSNldJEWf2k9l3HeTqdrEwsOsFcq74RiJECW34yA==
+bindings@*:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
+ integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==
+ dependencies:
+ file-uri-to-path "1.0.0"
+
blob@0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.4.tgz#bcf13052ca54463f30f9fc7e95b9a47630a94921"
@@ -4470,6 +4477,11 @@ file-loader@^3.0.1:
loader-utils "^1.0.2"
schema-utils "^1.0.0"
+file-uri-to-path@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
+ integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
+
fileset@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0"
@@ -4780,6 +4792,14 @@ getpass@^0.1.1:
dependencies:
assert-plus "^1.0.0"
+getrusage@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/getrusage/-/getrusage-1.0.0.tgz#0a59e877f70ca4708ad25b377ee05df4ccaba44c"
+ integrity sha1-Clnod/cMpHCK0ls3fuBd9MyrpEw=
+ dependencies:
+ bindings "*"
+ nan "^2.0.9"
+
gettext-extractor-vue@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/gettext-extractor-vue/-/gettext-extractor-vue-4.0.2.tgz#16e1cdbdaf37e5bdf3cb0aff63685bdc5e74e906"
@@ -7474,7 +7494,7 @@ mute-stream@0.0.7:
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
-nan@^2.12.1:
+nan@^2.0.9, nan@^2.12.1:
version "2.14.0"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==