diff options
author | Joyee Cheung <joyeec9h3@gmail.com> | 2017-01-16 02:59:13 +0800 |
---|---|---|
committer | Joyee Cheung <joyeec9h3@gmail.com> | 2017-01-31 03:03:57 +0800 |
commit | 60d77bd514d3dc65cfbb64ebb8ae1f364e8bf8eb (patch) | |
tree | 7090c026e7b5cdb9550d18be604e2d375a318800 /benchmark/_benchmark_progress.js | |
parent | ca3d131bd42afa0c68be6aeb27623d53eae547a1 (diff) | |
download | android-node-v8-60d77bd514d3dc65cfbb64ebb8ae1f364e8bf8eb.tar.gz android-node-v8-60d77bd514d3dc65cfbb64ebb8ae1f364e8bf8eb.tar.bz2 android-node-v8-60d77bd514d3dc65cfbb64ebb8ae1f364e8bf8eb.zip |
benchmark: add progress indicator to compare.js
* Print the progress bar and the current benchmark to stderr
when stderr is TTY and stdout is not.
* Allow cli arguments without values via setting.boolArgs
* Add --no-progress option
PR-URL: https://github.com/nodejs/node/pull/10823
Fixes: https://github.com/nodejs/node/issues/8659
Reviewed-By: Andreas Madsen <amwebdk@gmail.com>
Diffstat (limited to 'benchmark/_benchmark_progress.js')
-rw-r--r-- | benchmark/_benchmark_progress.js | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/benchmark/_benchmark_progress.js b/benchmark/_benchmark_progress.js new file mode 100644 index 0000000000..2a2a458c5c --- /dev/null +++ b/benchmark/_benchmark_progress.js @@ -0,0 +1,120 @@ +'use strict'; + +const readline = require('readline'); + +function pad(input, minLength, fill) { + var result = input + ''; + return fill.repeat(Math.max(0, minLength - result.length)) + result; +} + +function fraction(numerator, denominator) { + const fdenominator = denominator + ''; + const fnumerator = pad(numerator, fdenominator.length, ' '); + return `${fnumerator}/${fdenominator}`; +} + +function getTime(diff) { + const time = Math.ceil(diff[0] + diff[1] / 1e9); + const seconds = pad(time % 60, 2, '0'); + const minutes = pad(Math.floor(time / 60) % (60 * 60), 2, '0'); + const hours = pad(Math.floor(time / (60 * 60)), 2, '0'); + return `${hours}:${minutes}:${seconds}`; +} + +// A run is an item in the job queue: { binary, filename, iter } +// A config is an item in the subqueue: { binary, filename, iter, configs } +class BenchmarkProgress { + constructor(queue, benchmarks) { + this.queue = queue; // Scheduled runs. + this.benchmarks = benchmarks; // Filenames of scheduled benchmarks. + this.completedRuns = 0; // Number of completed runs. + this.scheduledRuns = queue.length; // Number of scheduled runs. + // Time when starting to run benchmarks. + this.startTime = process.hrtime(); + // Number of times each file will be run (roughly). + this.runsPerFile = queue.length / benchmarks.length; + this.currentFile = ''; // Filename of current benchmark. + this.currentFileConfig; // Configurations for current file + // Number of configurations already run for the current file. + this.completedConfig = 0; + // Total number of configurations for the current file + this.scheduledConfig = 0; + this.interval = 0; // result of setInterval for updating the elapsed time + } + + startQueue(index) { + this.kStartOfQueue = index; + this.currentFile = this.queue[index].filename; + this.interval = setInterval(() => { + if (this.completedRuns === this.scheduledRuns) { + clearInterval(this.interval); + } else { + this.updateProgress(); + } + }, 1000); + } + + startSubqueue(data, index) { + // This subqueue is generated by a new benchmark + if (data.name !== this.currentFile || index === this.kStartOfQueue) { + this.currentFile = data.name; + this.scheduledConfig = data.queueLength; + } + this.completedConfig = 0; + this.updateProgress(); + } + + completeConfig(data) { + this.completedConfig++; + this.updateProgress(); + } + + completeRun(job) { + this.completedRuns++; + this.updateProgress(); + } + + getProgress() { + // Get time as soon as possible. + const diff = process.hrtime(this.startTime); + + const completedRuns = this.completedRuns; + const scheduledRuns = this.scheduledRuns; + const finished = completedRuns === scheduledRuns; + + // Calculate numbers for fractions. + const runsPerFile = this.runsPerFile; + const completedFiles = Math.floor(completedRuns / runsPerFile); + const scheduledFiles = this.benchmarks.length; + const completedRunsForFile = finished ? runsPerFile : + completedRuns % runsPerFile; + const completedConfig = this.completedConfig; + const scheduledConfig = this.scheduledConfig; + + // Calculate the percentage. + let runRate = 0; // Rate of current incomplete run. + if (completedConfig !== scheduledConfig) { + runRate = completedConfig / scheduledConfig; + } + const completedRate = ((completedRuns + runRate) / scheduledRuns); + const percent = pad(Math.floor(completedRate * 100), 3, ' '); + + const caption = finished ? 'Done\n' : this.currentFile; + return `[${getTime(diff)}|% ${percent}` + + `| ${fraction(completedFiles, scheduledFiles)} files ` + + `| ${fraction(completedRunsForFile, runsPerFile)} runs ` + + `| ${fraction(completedConfig, scheduledConfig)} configs]` + + `: ${caption}`; + } + + updateProgress(finished) { + if (!process.stderr.isTTY || process.stdout.isTTY) { + return; + } + readline.clearLine(process.stderr); + readline.cursorTo(process.stderr, 0); + process.stderr.write(this.getProgress()); + } +} + +module.exports = BenchmarkProgress; |