This repository has been archived by the owner on Sep 30, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
node and browser benchmark runner #32
Merged
Merged
Changes from 88 commits
Commits
Show all changes
98 commits
Select commit
Hold shift + click to select a range
0df423e
fix: correct npm package name
tabcat 25e2b94
expose gc as a function
tabcat f2395fb
install isNode
tabcat a1d5f4c
add src/benchmarker.js
tabcat a082984
add needed bind for timeout callback
tabcat c8fe355
rework benchmarker into http client/server with cli
tabcat 67cf5f8
add commander to dependencies
tabcat 2846f25
fix program options usage
tabcat 3f35268
fix cli ls exec
tabcat d4b06a0
make child process exec async
tabcat b2fc619
use node-fetch instead of whatwg-fetch polyfill
tabcat b52eeb2
change benchmarker http-client addMetric api
tabcat ba0ee13
fix benchmarker server create and _handleResults
tabcat 9b6ea3c
logging over websockets
tabcat baeb965
remove unneeded timeout
tabcat 26b068c
write result json files to results folder
tabcat 94a6571
remove whatwg-fetch polyfill
tabcat 2a3f148
benchmarker better logging
tabcat 3c3a1d3
results over websockets
tabcat c4a2a33
error logging and use stdout instead of console.log
tabcat 045cc37
remove http from benchmarker server
tabcat 7fe4493
prep for browser support
tabcat ad392e3
install webpack middleware and express
a1cd244
install html-webpack-plugin
9db9d06
install val-loader
7856bb1
downgrade webpack to v4
48430e4
downgrade html-webpack-plugin to support webpack4
e30a7b8
downgrade val-loader
fa7554b
add newlines for cancel/complete status
62d9c7a
manual browser support (no puppeteer yet)
1192ee3
automate browser benchmarks with puppeteer
tabcat 6d64605
removed uneeded promisify
tabcat 04ad0b0
use fork over exec in benchmarker cli
tabcat 2338cd4
move webpack to its own thread
tabcat d0ad874
ensure split works for large ls return
tabcat a5cc0e0
cleanup and minor changes
tabcat ac7b3c4
use open ports, remove port argument
tabcat 5bfa43b
install ws websocket server
tabcat d03d3d2
create results dir path on results
tabcat 8699a66
move server variable into runBenchmarks
tabcat 3cbe290
fix typo
tabcat 34c5e26
add bundling... message
tabcat 8d20f0c
use console.log for log messages
tabcat 25a2d22
fix window.performance.memory accuracy
tabcat dd69391
use already opened browser page
tabcat 59d5e8a
add puppeteer to deps
tabcat 9903131
move default metrics to separate file
tabcat e5fc31a
get ready to build fixtures
tabcat 3a0745f
edit package deps and npm audit fix
tabcat 76385c1
ignore fixtures dir
tabcat e4107e9
refactor benchmarker; all working but reports
tabcat cf77394
remove old benchmark runner files
tabcat cf5556b
edit deps; commit package and package-lock
tabcat 92ada32
base working
tabcat 2278a9f
add log-load benchmark
tabcat 7c3d93c
change benchmark setting
tabcat bb7a78a
use execBenchmarkPath variable
tabcat d3fd012
stop using fixtures
tabcat 2e5b35e
more report outputs
tabcat 2e7df88
add ordered benchmarks
tabcat 2b1035f
add process-results and report util file
tabcat bc6707c
get percent change for time metric
tabcat bc13cb3
remove getLabel from process-results
tabcat 3e98fa4
make dir for output path
tabcat 6b8b2e9
no fixtures or hard coded port; small cleanup
tabcat f204d33
move Report component to parent dir
tabcat 91015d8
change option order
tabcat c8a89e2
optionally track mem/cpu
tabcat f36bb87
benchmarks path param for cli
tabcat c229048
add catch to webpackServer call
tabcat 9f5ec91
add benchmarking... console message
tabcat 9adb611
fix webpack-server
tabcat 0bb9301
remove local benchmarks
tabcat 490450e
no written output by default
tabcat 9aae43b
remove --no-output option
tabcat f2af8e6
fix avg processed metric
tabcat 37654bf
change benchmarker server variable name
tabcat 59d1be5
reuse webpack port for indexedDb
tabcat 282d227
change baselines option flag
tabcat 0264cd7
reword opt description; change -b default
tabcat 0935a9c
add basic usage to README.md
tabcat 9696217
remove fixtures from gitignore
tabcat c22f492
remove tests for now
tabcat bdca18b
remove runPlace leftover from run.js
tabcat 47b9f5e
browser name property for execBenchmarks
tabcat 379a9b5
static webpack port
tabcat 1dcbdec
make reporter/process-results.js more readable
tabcat 4e247fa
fix: webpack-entry use run func again
tabcat 0ee6f76
change tempdir name for benchmark runner
tabcat d36133e
remove outdated comment
tabcat ea6bd94
small style edit cli.js
tabcat 149fab5
check for baseline path exist
tabcat cbaed0f
add baseline comparison example
tabcat 3aa8176
add basic end2end and cli option tests
tabcat 4986962
add docs on creating benchmarks
tabcat 87981de
add 30 sec timeout to tests
tabcat 94a882b
support benchmark hooks
tabcat 80ac3ae
console report spacing and negative array length
tabcat File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Large diffs are not rendered by default.
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 |
---|---|---|
|
@@ -4,16 +4,39 @@ | |
"description": "OrbitDB Benchmark Runner", | ||
"main": "./src/index.js", | ||
"bin": { | ||
"benchmark-runner": "./src/cli.js" | ||
}, | ||
"scripts": { | ||
"test": "nyc mocha" | ||
"benchmarker": "./src/cli.js" | ||
}, | ||
"scripts": {}, | ||
"author": "mistakia", | ||
"license": "MIT", | ||
"dependencies": { | ||
"expose-gc": "^1.0.0", | ||
"yargs": "^15.4.1" | ||
"@babel/core": "^7.13.10", | ||
"@babel/preset-env": "^7.13.12", | ||
"@babel/preset-react": "^7.12.13", | ||
"@nivo/core": "^0.67.0", | ||
"@nivo/line": "^0.67.0", | ||
"babel-loader": "^8.2.2", | ||
"bootstrap": "^4.6.0", | ||
"commander": "^7.1.0", | ||
"css-loader": "^5.1.3", | ||
"express": "^4.17.1", | ||
"html-webpack-plugin": "^4.5.2", | ||
"inline-assets-html-plugin": "^1.0.0", | ||
"is-node": "^1.0.2", | ||
"puppeteer": "^8.0.0", | ||
"react": "^17.0.2", | ||
"react-bootstrap": "^1.5.2", | ||
"react-dom": "^17.0.2", | ||
"style-loader": "^2.0.0", | ||
"val-loader": "^2.1.2", | ||
"webpack": "^4.46.0", | ||
"webpack-dev-middleware": "^4.1.0", | ||
"ws": "^7.4.4" | ||
}, | ||
"devDependencies": { | ||
"ipfs": "^0.54.4", | ||
"orbit-db": "^0.26.1", | ||
"standard": "^14.3.4" | ||
}, | ||
"localMaintainers": [ | ||
"hajamark <[email protected]>", | ||
|
@@ -32,13 +55,6 @@ | |
"homepage": "https://github.com/orbitdb/benchmark-runner#readme", | ||
"bugs": "https://github.com/orbitdb/benchmark-runner/issues", | ||
"repository": "github:orbitdb/benchmark-runner", | ||
"devDependencies": { | ||
"chai": "^4.2.0", | ||
"mocha": "^8.1.3", | ||
"nyc": "^15.1.0", | ||
"sinon": "^9.0.3", | ||
"standard": "^14.3.4" | ||
}, | ||
"standard": { | ||
"env": "mocha" | ||
} | ||
|
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,116 @@ | ||
'use strict' | ||
const isNode = require('is-node') | ||
const nodeDir = (dir) => require('path').join(dir, 'node') | ||
const getWebSocket = () => isNode | ||
? require('ws') | ||
: window.WebSocket | ||
const { makeId, withInfo, creators } = require('./ws-action') | ||
const { | ||
timeMetric, | ||
cpuUsageMetric, | ||
memoryUsedMetric, | ||
memoryTotalMetric | ||
} = require('./metrics') | ||
|
||
class Benchmarker { | ||
constructor (ws, dir) { | ||
this._ws = ws | ||
this.dir = isNode ? nodeDir(dir) : dir | ||
this._timeout = null | ||
|
||
this.isNode = isNode | ||
this.id = makeId() | ||
this.info = { | ||
id: this.id, | ||
name: `benchmark-${this.id}`, | ||
env: isNode ? 'node' : 'browser', | ||
metrics: [] | ||
} | ||
this._interval = 1000 // record metrics every this many ms | ||
|
||
this.metrics = [] | ||
this.addMetric(timeMetric) | ||
} | ||
|
||
static async create (host, dir) { | ||
const ws = await new Promise(resolve => { | ||
const ws = new (getWebSocket())(`ws://${host}`) | ||
ws.onopen = () => resolve(ws) | ||
}) | ||
return new Benchmarker(ws, dir) | ||
} | ||
|
||
async close () { | ||
if (this._ws.readyState !== 3) { | ||
await new Promise(resolve => { | ||
this._ws.onclose = () => resolve() | ||
this._ws.close() | ||
}) | ||
} | ||
} | ||
|
||
trackMemory () { | ||
this.addMetric(memoryUsedMetric) | ||
this.addMetric(memoryTotalMetric) | ||
} | ||
|
||
trackCpu () { | ||
if (isNode) this.addMetric(cpuUsageMetric) | ||
} | ||
|
||
addMetric ({ name, get }) { | ||
if (this.info.metrics.includes(name)) { | ||
throw new Error('a metric with that name already exists') | ||
} | ||
if (this._timeout) { | ||
throw new Error('metrics have already started being recorded') | ||
} | ||
this.metrics.push({ name, get }) | ||
this.info.metrics = this.metrics.map(m => m.name) | ||
} | ||
|
||
setInterval (interval) { | ||
if (typeof interval !== 'number') { | ||
throw new Error('interval must be a number') | ||
} | ||
if (this._timeout) { | ||
throw new Error('metrics have already started being recorded') | ||
} | ||
this._interval = interval | ||
} | ||
|
||
setBenchmarkName (name) { | ||
this.info.name = name.toString() | ||
} | ||
|
||
log (msg) { | ||
this._sendAction(creators.LOG(msg)) | ||
} | ||
|
||
_sendAction (action) { | ||
this._ws.send(JSON.stringify(withInfo(this.info)(action))) | ||
} | ||
|
||
_recordMetrics () { | ||
this._sendAction(creators.SEGMENT(this.metrics.map(({ get }) => get()))) | ||
} | ||
|
||
startRecording () { | ||
if (!this._timeout) { | ||
const interval = this._interval | ||
const repeater = () => { | ||
this._recordMetrics() | ||
this._timeout = setTimeout(repeater.bind(this), interval) | ||
} | ||
repeater() | ||
} | ||
} | ||
|
||
stopRecording () { | ||
clearTimeout(this._timeout) | ||
this._timeout = null | ||
this._recordMetrics() | ||
} | ||
} | ||
|
||
module.exports = Benchmarker |
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,71 @@ | ||
'use strict' | ||
const isNode = require('is-node') | ||
const useMetricState = (state, get) => () => { | ||
const { newState, next } = get(state) | ||
state = newState | ||
return next | ||
} | ||
|
||
const timeMetric = { | ||
name: 'time', | ||
get: useMetricState(0, (state) => { | ||
const now = Date.now() | ||
return { | ||
newState: state || now, | ||
next: now - (state || now) // on first metric sample: now - now, aka 0 | ||
} | ||
}) | ||
} | ||
|
||
const ns2ms = (ms) => ms / 1000 | ||
const cpuUsageMetric = { | ||
name: 'cpu usage', | ||
get: useMetricState(undefined, (state) => { | ||
const time = Date.now() | ||
const { user, system } = process.cpuUsage() | ||
const total = ns2ms(user) + ns2ms(system) | ||
return { | ||
newState: { total, time }, | ||
next: state | ||
// cpu usage to percent | ||
? Math.round(100 * ((total - state.total) / (time - state.time))) | ||
: 0 | ||
} | ||
}) | ||
} | ||
|
||
const memorySample = () => { | ||
const sample = isNode | ||
? process.memoryUsage() | ||
: window.performance.memory | ||
const memory = { | ||
total: null, | ||
used: null | ||
} | ||
// denominated in bytes | ||
if (isNode) { | ||
memory.total = sample.heapTotal | ||
memory.used = sample.heapUsed | ||
} else { | ||
memory.total = sample.totalJSHeapSize | ||
memory.used = sample.usedJSHeapSize | ||
} | ||
return memory | ||
} | ||
const toMegabytes = (bytes) => bytes / 1000000 | ||
const memoryUsedMetric = { | ||
name: 'heap used', | ||
get: () => toMegabytes(memorySample().used) | ||
} | ||
const memoryTotalMetric = { | ||
name: 'heap total', | ||
get: () => toMegabytes(memorySample().total) | ||
} | ||
|
||
module.exports = { | ||
useMetricState, | ||
timeMetric, | ||
cpuUsageMetric, | ||
memoryUsedMetric, | ||
memoryTotalMetric | ||
} |
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,39 @@ | ||
'use strict' | ||
const WebSocket = require('ws') | ||
const { parse, types } = require('./ws-action') | ||
const logMessage = (id, msg) => | ||
`benchmark id:${id} | ||
${msg} | ||
` | ||
|
||
class BenchmarkerServer { | ||
constructor ({ port } = {}) { | ||
this._wss = new WebSocket.Server({ port: port || 0 }) | ||
this._wss.on('connection', this._handleWsConnection.bind(this)) | ||
this.address = this._wss.address.bind(this._wss) | ||
this.results = {} | ||
} | ||
|
||
static create (opts) { return new BenchmarkerServer(opts) } | ||
|
||
async _handleWsConnection (ws) { | ||
ws.on('message', m => { | ||
const { info, type, msg } = parse(m) | ||
switch (type) { | ||
case types.LOG: | ||
console.log(logMessage(info.id, msg)) | ||
break | ||
case types.SEGMENT: { | ||
const { name, env } = info | ||
if (!this.results[name]) this.results[name] = {} | ||
if (!this.results[name][env]) this.results[name][env] = info | ||
if (!this.results[name][env].recorded) this.results[name][env].recorded = [] | ||
this.results[name][env].recorded.push(msg) | ||
break | ||
} | ||
} | ||
}) | ||
} | ||
} | ||
|
||
module.exports = BenchmarkerServer |
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,22 @@ | ||
'use strict' | ||
|
||
const action = {} | ||
|
||
action.types = { | ||
LOG: 'LOG', | ||
SEGMENT: 'SEGMENT' | ||
} | ||
|
||
action.creators = { | ||
[action.types.LOG]: (msg) => | ||
({ type: action.types.LOG, msg }), | ||
[action.types.SEGMENT]: (msg) => | ||
({ type: action.types.SEGMENT, msg }) | ||
} | ||
|
||
action.makeId = () => Date.now() | ||
action.withInfo = (info) => (action) => ({ info, ...action }) | ||
|
||
action.parse = (action) => JSON.parse(action) | ||
|
||
module.exports = action |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we change the name of the repo to
orbit-db-benchmarker
? Thinking about consistency.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this could be changed to anything or kept the same, i chose the different name originally so it didnt conflict. probably good to have the package and repo the same name though (they are different right now; repo: benchmark-runner, package: orbit-db-benchmark-runner). shorter name probably better. also keep in mind the benchmarker doesnt have anything written in that makes it specific to benchmarking orbitdb, it can run benchmarks for anything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright let's just leave it as is for now until it becomes a real problem