forked from badges/shields
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make it easier to benchmark and profile the code (badges#4780)
* Make it easier to benchmark and profile the code * Remove unnecessary escape * Clarify that the backend server is started without the frontend * Add missing NODE_CONFIG_ENV environment variable * Add error message when user has not included console.time statements * Fix lint issue * Handle multiple console.time statements * Switch NODE_CONFIG_ENV to test * Switch to const as variable never re-assigned
- Loading branch information
Showing
11 changed files
with
138 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -113,3 +113,6 @@ service-definitions.yml | |
|
||
# Rendered API docs | ||
/api-docs/ | ||
|
||
# Flamebearer | ||
flamegraph.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# Performance testing | ||
|
||
Shields has some basic tooling available to help you get started with | ||
performance testing. | ||
|
||
## Benchmarking the badge generation | ||
|
||
Want to micro-benchmark a section of the code responsible for generating the | ||
static badges? Follow these two simple steps: | ||
|
||
1. Surround the code you want to time with `console.time` and `console.timeEnd` | ||
statements. For example: | ||
|
||
``` | ||
console.time('makeBadge') | ||
const svg = makeBadge(badgeData) | ||
console.timeEnd('makeBadge') | ||
``` | ||
|
||
2. Run `npm run benchmark:badge` in your terminal. An average timing will | ||
be displayed! | ||
|
||
If you want to change the number of iterations in the benchmark, you can modify | ||
the values specified by the `benchmark:badge` script in _package.json_. If | ||
you want to benchmark a specific code path not covered by the static badge, you | ||
can modify the badge URL in _scripts/benchmark-performance.js_. | ||
|
||
## Profiling the full code | ||
|
||
Want to have an overview of how the entire application is performing? Simply | ||
run `npm run profile:server` in your terminal. This will start the | ||
backend server (i.e. without the frontend) in profiling mode and any requests | ||
you make on `localhost:8080` will generate data in a file with a name | ||
similar to _isolate-00000244AB6ED3B0-11920-v8.log_. | ||
|
||
You can then make use of this profiling data in various tools, for example | ||
[flamebearer](https://github.com/mapbox/flamebearer): | ||
|
||
``` | ||
npm install -g flamebearer | ||
node --prof-process --preprocess -j isolate-00000244AB6ED3B0-11920-v8.log | flamebearer | ||
``` | ||
|
||
An example output is the following: | ||
 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
'use strict' | ||
|
||
const config = require('config').util.toObject() | ||
const got = require('got') | ||
const minimist = require('minimist') | ||
const Server = require('../core/server/server') | ||
|
||
async function main() { | ||
const server = new Server(config) | ||
await server.start() | ||
const args = minimist(process.argv) | ||
const iterations = parseInt(args.iterations) || 10000 | ||
for (let i = 0; i < iterations; ++i) { | ||
await got(`${server.baseUrl}badge/coverage-${i}-green.svg`) | ||
} | ||
await server.stop() | ||
} | ||
|
||
;(async () => { | ||
try { | ||
await main() | ||
} catch (e) { | ||
console.error(e) | ||
process.exit(1) | ||
} | ||
})() |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
'use strict' | ||
|
||
const readline = require('readline') | ||
const minimist = require('minimist') | ||
|
||
async function captureTimings(warmupIterations) { | ||
const rl = readline.createInterface({ | ||
input: process.stdin, | ||
}) | ||
|
||
const times = {} | ||
let timingsCount = 0 | ||
let labelsCount = 0 | ||
const timing = /^(.+): ([0-9.]+)ms$/i | ||
|
||
for await (const line of rl) { | ||
const match = timing.exec(line) | ||
if (match) { | ||
labelsCount = Object.keys(times).length | ||
if (timingsCount > warmupIterations * labelsCount) { | ||
const label = match[1] | ||
const time = parseFloat(match[2]) | ||
times[label] = time + (times[label] || 0) | ||
} | ||
++timingsCount | ||
} | ||
} | ||
return { times, iterations: timingsCount / labelsCount } | ||
} | ||
|
||
function logResults({ times, iterations, warmupIterations }) { | ||
if (isNaN(iterations)) { | ||
console.log( | ||
`No timings captured. Have you included console.time statements in the badge creation code path?` | ||
) | ||
} else { | ||
const timedIterations = iterations - warmupIterations | ||
for (const [label, time] of Object.entries(times)) { | ||
const averageTime = time / timedIterations | ||
console.log( | ||
`Average '${label}' time over ${timedIterations} iterations: ${averageTime}ms` | ||
) | ||
} | ||
} | ||
} | ||
|
||
async function main() { | ||
const args = minimist(process.argv) | ||
const warmupIterations = parseInt(args['warmup-iterations']) || 100 | ||
const { times, iterations } = await captureTimings(warmupIterations) | ||
logResults({ times, iterations, warmupIterations }) | ||
} | ||
|
||
;(async () => { | ||
try { | ||
await main() | ||
} catch (e) { | ||
console.error(e) | ||
process.exit(1) | ||
} | ||
})() |