Skip to content

Commit

Permalink
test,v8: skip less and stabilize test-linux-perf.js
Browse files Browse the repository at this point in the history
Co-authored-by: Matheus Marchini <mat@mmarchini.me>

PR-URL: nodejs#27364
Refs: nodejs/build#1774
Reviewed-By: Matheus Marchini <mat@mmarchini.me>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
  • Loading branch information
refack committed Jun 6, 2019
1 parent a8277dd commit 546d6cd
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 39 deletions.
27 changes: 9 additions & 18 deletions test/fixtures/linux-perf.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,17 @@
'use strict';

const crypto = require('crypto');
const { spawnSync } = require("child_process");
const sleepTime = new Number(process.argv[2] || "0.1");
const repeat = new Number(process.argv[3]) || 5;

// Functions should be complex enough for V8 to run them a few times before
// compiling, but not complex enough to always stay in interpreted mode. They
// should also take some time to run, otherwise Linux perf might miss them
// entirely even when sampling at a high frequency.
function functionOne(i) {
for (let j=i; j > 0; j--) {
crypto.createHash('md5').update(functionTwo(i, j)).digest("hex");
}
function functionOne() {
functionTwo();
}

function functionTwo(x, y) {
let data = ((((x * y) + (x / y)) * y) ** (x + 1)).toString();
if (x % 2 == 0) {
return crypto.createHash('md5').update(data.repeat((x % 100) + 1)).digest("hex");
} else {
return crypto.createHash('md5').update(data.repeat((y % 100) + 1)).digest("hex");
}
function functionTwo() {
spawnSync('sleep', [`${sleepTime}`]);
}

for (let i = 0; i < 1000; i++) {
functionOne(i);
for (let i = 0; i < repeat; i++) {
functionOne();
}
73 changes: 52 additions & 21 deletions test/v8-updates/test-linux-perf.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,53 @@ tmpdir.refresh();
if (process.config.variables.node_shared)
common.skip("can't test Linux perf with shared libraries yet");

const perfArgs = [
if (!common.isLinux)
common.skip('only testing Linux for now');

const frequency = 99;

const repeat = 5;

// Expected number of samples we'll capture per repeat
const sampleCount = 10;
const sleepTime = sampleCount * (1.0 / frequency);

const perfFlags = [
'record',
'-F999',
`-F${frequency}`,
'-g',
'--',
process.execPath,
];

const nodeCommonFlags = [
'--perf-basic-prof',
'--interpreted-frames-native-stack',
'--no-turbo-inlining', // Otherwise simple functions might get inlined.
];

const perfInterpretedFramesArgs = [
...perfFlags,
'--',
process.execPath,
...nodeCommonFlags,
'--no-opt',
fixtures.path('linux-perf.js'),
`${sleepTime}`,
`${repeat}`,
];

const perfCompiledFramesArgs = [
...perfFlags,
'--',
process.execPath,
...nodeCommonFlags,
'--always-opt',
fixtures.path('linux-perf.js'),
`${sleepTime}`,
`${repeat}`,
];

const perfArgsList = [
perfInterpretedFramesArgs, perfCompiledFramesArgs
];

const perfScriptArgs = [
Expand All @@ -43,33 +80,27 @@ const options = {
encoding: 'utf-8',
};

if (!common.isLinux)
common.skip('only testing Linux for now');

const perf = spawnSync('perf', perfArgs, options);

if (perf.error && perf.error.errno === 'ENOENT')
common.skip('perf not found on system');

if (perf.status !== 0) {
common.skip(`Failed to execute perf: ${perf.stderr}`);
}
let output = '';

const perfScript = spawnSync('perf', perfScriptArgs, options);
for (const perfArgs of perfArgsList) {
const perf = spawnSync('perf', perfArgs, options);
assert.ifError(perf.error);
if (perf.status !== 0)
throw new Error(`Failed to execute 'perf': ${perf.stderr}`);

if (perf.error)
common.skip(`perf script aborted: ${perf.error.errno}`);
const perfScript = spawnSync('perf', perfScriptArgs, options);
assert.ifError(perfScript.error);
if (perfScript.status !== 0)
throw new Error(`Failed to execute perf script: ${perfScript.stderr}`);

if (perfScript.status !== 0) {
common.skip(`Failed to execute perf script: ${perfScript.stderr}`);
output += perfScript.stdout;
}

const interpretedFunctionOneRe = /InterpretedFunction:functionOne/;
const compiledFunctionOneRe = /LazyCompile:\*functionOne/;
const interpretedFunctionTwoRe = /InterpretedFunction:functionTwo/;
const compiledFunctionTwoRe = /LazyCompile:\*functionTwo/;

const output = perfScript.stdout;

assert.ok(output.match(interpretedFunctionOneRe),
"Couldn't find interpreted functionOne()");
Expand Down

0 comments on commit 546d6cd

Please sign in to comment.