Skip to content

Commit 1b51a68

Browse files
mrickardbizob2828
andauthored
test: Updated benchmark test results to output result files (#2350)
Signed-off-by: mrickard <[email protected]> Co-authored-by: Bob Evans <[email protected]>
1 parent 2a2a65d commit 1b51a68

File tree

12 files changed

+205
-205
lines changed

12 files changed

+205
-205
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,5 @@ test/versioned-external/TEMP_TESTS
1919
nr-security-home
2020
# Needed for testing
2121
!test/integration/moduleLoading/node_modules
22+
# benchmark results
23+
benchmark_results

bin/compare-bench-results.js

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const processFile = async (file) => {
2727
}
2828
}
2929

30-
const reportResults = (resultFiles) => {
30+
const reportResults = async (resultFiles) => {
3131
const baseline = resultFiles[0]
3232
const downstream = resultFiles[1]
3333

@@ -88,8 +88,7 @@ const reportResults = (resultFiles) => {
8888
allPassing = allPassing && filePassing
8989

9090
return [
91-
'<details>',
92-
`<summary>${testFile}: ${passMark(filePassing)}</summary>`,
91+
`#### ${testFile}: ${passMark(filePassing)}`,
9392
'',
9493
results,
9594
'',
@@ -105,11 +104,22 @@ const reportResults = (resultFiles) => {
105104
console.log('')
106105
}
107106

108-
console.log(`### Benchmark Results: ${passMark(allPassing)}`)
109-
console.log('')
110-
console.log('### Details')
111-
console.log('_Lower is better._')
112-
console.log(details)
107+
const date = new Date()
108+
let content = `### Benchmark Results: ${passMark(allPassing)}\n\n\n\n`
109+
content += `${date.toISOString()}\n\n`
110+
content += '### Details\n\n'
111+
content += '_Lower is better._\n\n'
112+
content += `${details}\n`
113+
114+
const resultPath = 'benchmark_results'
115+
try {
116+
await fs.stat(resultPath)
117+
} catch (e) {
118+
await fs.mkdir(resultPath)
119+
}
120+
const fileName = `${resultPath}/comparison_${date.getTime()}.md`
121+
await fs.writeFile(fileName, content)
122+
console.log(`Done! Benchmark test comparison written to ${fileName}`)
113123

114124
if (!allPassing) {
115125
process.exitCode = -1
@@ -118,9 +128,11 @@ const reportResults = (resultFiles) => {
118128

119129
const iterate = async () => {
120130
const files = process.argv.slice(2)
121-
const results = files.map(async (file) => {
122-
return processFile(file)
123-
})
131+
const results = await Promise.all(
132+
files.map(async (file) => {
133+
return await processFile(file)
134+
})
135+
)
124136
reportResults(results)
125137
}
126138

bin/run-bench.js

Lines changed: 73 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,20 @@
55

66
'use strict'
77

8-
/* eslint sonarjs/cognitive-complexity: ["error", 21] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
9-
108
const cp = require('child_process')
119
const glob = require('glob')
1210
const path = require('path')
1311
const { errorAndExit } = require('./utils')
12+
const fs = require('fs/promises')
1413

1514
const cwd = path.resolve(__dirname, '..')
1615
const benchpath = path.resolve(cwd, 'test/benchmark')
1716

1817
const tests = []
18+
const testPromises = []
1919
const globs = []
2020
const opts = Object.create(null)
2121

22-
// replacement for former async-lib cb
23-
const testCb = (err, payload) => {
24-
if (err) {
25-
console.error(err)
26-
return
27-
}
28-
return payload
29-
}
30-
3122
process.argv.slice(2).forEach(function forEachFileArg(file) {
3223
if (/^--/.test(file)) {
3324
opts[file.substring(2)] = true
@@ -48,105 +39,118 @@ if (tests.length === 0 && globs.length === 0) {
4839
globs.push(path.join(benchpath, '*.bench.js'), path.join(benchpath, '**/*.bench.js'))
4940
}
5041

51-
class ConsolePrinter {
52-
/* eslint-disable no-console */
53-
addTest(name, child) {
54-
console.log(name)
55-
child.stdout.on('data', (d) => process.stdout.write(d))
56-
child.stderr.on('data', (d) => process.stderr.write(d))
57-
child.once('exit', () => console.log(''))
58-
}
59-
60-
finish() {
61-
console.log('')
62-
}
63-
/* eslint-enable no-console */
64-
}
65-
66-
class JSONPrinter {
42+
class Printer {
6743
constructor() {
6844
this._tests = Object.create(null)
6945
}
7046

7147
addTest(name, child) {
7248
let output = ''
73-
this._tests[name] = null
7449
child.stdout.on('data', (d) => (output += d.toString()))
75-
child.stdout.on('end', () => (this._tests[name] = JSON.parse(output)))
7650
child.stderr.on('data', (d) => process.stderr.write(d))
51+
52+
this._tests[name] = new Promise((resolve) => {
53+
child.stdout.on('end', () => {
54+
try {
55+
this._tests[name] = JSON.parse(output)
56+
} catch (e) {
57+
console.error(`Error parsing test results for ${name}`, e)
58+
this._tests[name] = output
59+
}
60+
resolve()
61+
})
62+
})
7763
}
7864

79-
finish() {
80-
/* eslint-disable no-console */
81-
console.log(JSON.stringify(this._tests, null, 2))
82-
/* eslint-enable no-console */
65+
async finish() {
66+
if (opts.console) {
67+
/* eslint-disable no-console */
68+
console.log(JSON.stringify(this._tests, null, 2))
69+
/* eslint-enable no-console */
70+
}
71+
const resultPath = 'benchmark_results'
72+
try {
73+
await fs.stat(resultPath)
74+
} catch (e) {
75+
await fs.mkdir(resultPath)
76+
}
77+
const content = JSON.stringify(this._tests, null, 2)
78+
const fileName = `${resultPath}/benchmark_${new Date().getTime()}.json`
79+
await fs.writeFile(fileName, content)
80+
console.log(`Done! Test output written to ${fileName}`)
8381
}
8482
}
8583

8684
run()
8785

8886
async function run() {
89-
const printer = opts.json ? new JSONPrinter() : new ConsolePrinter()
87+
const printer = new Printer()
88+
let currentTest = 0
9089

91-
const resolveGlobs = (cb) => {
90+
const resolveGlobs = () => {
9291
if (!globs.length) {
93-
cb()
92+
console.error(`There aren't any globs to resolve.`)
93+
return
9494
}
95-
const afterGlobbing = (err, resolved) => {
96-
if (err) {
97-
errorAndExit(err, 'Failed to glob', -1)
98-
cb(err)
95+
const afterGlobbing = (resolved) => {
96+
if (!resolved) {
97+
return errorAndExit(new Error('Failed to glob'), 'Failed to glob', -1)
9998
}
100-
resolved.forEach(function mergeResolved(files) {
101-
files.forEach(function mergeFile(file) {
102-
if (tests.indexOf(file) === -1) {
103-
tests.push(file)
104-
}
105-
})
106-
})
107-
cb() // ambient scope
99+
100+
function mergeFile(file) {
101+
if (tests.indexOf(file) === -1) {
102+
tests.push(file)
103+
}
104+
}
105+
function mergeResolved(files) {
106+
files.forEach(mergeFile)
107+
}
108+
109+
return resolved.forEach(mergeResolved)
108110
}
109111

110112
const globbed = globs.map((item) => glob.sync(item))
111-
return afterGlobbing(null, globbed)
113+
return afterGlobbing(globbed)
112114
}
113115

114-
const spawnEachFile = (file, spawnCb) => {
116+
const spawnEachFile = async (file) => {
115117
const test = path.relative(benchpath, file)
116118

117119
const args = [file]
118120
if (opts.inspect) {
119121
args.unshift('--inspect-brk')
120122
}
121123

122-
const child = cp.spawn('node', args, { cwd: cwd, stdio: 'pipe' })
123-
printer.addTest(test, child)
124+
const child = cp.spawn('node', args, { cwd: cwd, stdio: 'pipe', silent: true })
124125

125-
child.on('error', spawnCb)
126+
child.on('error', (err) => {
127+
console.error(`Error in child test ${test}`, err)
128+
throw err
129+
})
126130
child.on('exit', function onChildExit(code) {
131+
currentTest = currentTest + 1
127132
if (code) {
128-
spawnCb(new Error('Benchmark exited with code ' + code))
133+
console.error(`(${currentTest}/${tests.length}) FAILED: ${test} exited with code ${code}`)
134+
return
129135
}
130-
spawnCb()
136+
console.log(`(${currentTest}/${tests.length}) ${file} has completed`)
131137
})
138+
printer.addTest(test, child)
132139
}
133140

134-
const afterSpawnEachFile = (err, cb) => {
135-
if (err) {
136-
errorAndExit(err, 'Spawning failed:', -2)
137-
return cb(err)
138-
}
139-
cb()
140-
}
141-
142-
const runBenchmarks = async (cb) => {
141+
const runBenchmarks = async () => {
143142
tests.sort()
144-
await tests.forEach((file) => spawnEachFile(file, testCb))
145-
await afterSpawnEachFile(null, testCb)
146-
return cb()
143+
for await (const file of tests) {
144+
await spawnEachFile(file)
145+
}
146+
const keys = Object.keys(printer._tests)
147+
for (const key of keys) {
148+
testPromises.push(printer._tests[key])
149+
}
147150
}
148151

149-
await resolveGlobs(testCb)
150-
await runBenchmarks(testCb)
152+
await resolveGlobs()
153+
await runBenchmarks()
154+
await Promise.all(testPromises)
151155
printer.finish()
152156
}

test/benchmark/async-hooks.bench.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ const benchmark = require('../lib/benchmark')
99

1010
const suite = benchmark.createBenchmark({
1111
name: 'async hooks',
12-
async: true,
1312
fn: runBenchmark
1413
})
1514

@@ -52,10 +51,11 @@ tests.forEach((test) => suite.add(test))
5251

5352
suite.run()
5453

55-
function runBenchmark(agent, cb) {
54+
function runBenchmark() {
5655
let p = Promise.resolve()
5756
for (let i = 0; i < 300; ++i) {
5857
p = p.then(function noop() {})
5958
}
60-
p.then(cb)
59+
60+
return p
6161
}

test/benchmark/datastore-shim/recordBatch.bench.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,31 +19,34 @@ function makeInit(instrumented) {
1919

2020
suite.add({
2121
name: 'instrumented operation',
22-
async: true,
2322
initialize: makeInit(true),
2423
agent: {},
25-
fn: function (agent, done) {
26-
testDatastore.testBatch('test', done)
24+
fn: function () {
25+
return new Promise((resolve) => {
26+
testDatastore.testBatch('test', resolve)
27+
})
2728
}
2829
})
2930

3031
suite.add({
3132
name: 'uninstrumented operation',
3233
initialize: makeInit(false),
33-
async: true,
34-
fn: function (agent, done) {
35-
testDatastore.testBatch('test', done)
34+
fn: function () {
35+
return new Promise((resolve) => {
36+
testDatastore.testBatch('test', resolve)
37+
})
3638
}
3739
})
3840

3941
suite.add({
4042
name: 'instrumented operation in transaction',
41-
async: true,
4243
agent: {},
4344
initialize: makeInit(true),
4445
runInTransaction: true,
45-
fn: function (agent, done) {
46-
testDatastore.testBatch('test', done)
46+
fn: function () {
47+
return new Promise((resolve) => {
48+
testDatastore.testBatch('test', resolve)
49+
})
4750
}
4851
})
4952

test/benchmark/datastore-shim/recordOperation.bench.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,31 +19,34 @@ function makeInit(instrumented) {
1919

2020
suite.add({
2121
name: 'instrumented operation in transaction',
22-
async: true,
2322
agent: {},
2423
initialize: makeInit(true),
2524
runInTransaction: true,
26-
fn: function (agent, done) {
27-
testDatastore.testOp(done)
25+
fn: function () {
26+
return new Promise((resolve) => {
27+
testDatastore.testOp(resolve)
28+
})
2829
}
2930
})
3031

3132
suite.add({
3233
name: 'instrumented operation',
33-
async: true,
3434
initialize: makeInit(true),
3535
agent: {},
36-
fn: function (agent, done) {
37-
testDatastore.testOp(done)
36+
fn: function () {
37+
return new Promise((resolve) => {
38+
testDatastore.testOp(resolve)
39+
})
3840
}
3941
})
4042

4143
suite.add({
4244
name: 'uninstrumented operation',
4345
initialize: makeInit(false),
44-
async: true,
45-
fn: function (agent, done) {
46-
testDatastore.testOp(done)
46+
fn: function () {
47+
return new Promise((resolve) => {
48+
testDatastore.testOp(resolve)
49+
})
4750
}
4851
})
4952

0 commit comments

Comments
 (0)