diff options
author | Martin Hanzel <mhanzel@gitlab.com> | 2019-06-05 09:14:36 +0200 |
---|---|---|
committer | Martin Hanzel <mhanzel@gitlab.com> | 2019-06-05 09:14:36 +0200 |
commit | 01bf2c41efa9b3bafb77aa2bc38cdc8e669c1b45 (patch) | |
tree | 29bb17ead16c7e49bc6887b9fff60f8bdab1e115 | |
parent | 5d618ead71d4ee9bb54926f764a77a9d90b9912b (diff) | |
download | gitlab-ce-mh/cpu-time.tar.gz |
Add getrusage packagemh/cpu-time
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | spec/frontend/helpers/cpu_time.js | 33 | ||||
-rw-r--r-- | spec/frontend/helpers/cpu_time_spec.js | 72 | ||||
-rw-r--r-- | spec/frontend/helpers/timeout.js | 32 | ||||
-rw-r--r-- | yarn.lock | 22 |
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== |