summaryrefslogtreecommitdiff
path: root/benchmark/_benchmark_progress.js
diff options
context:
space:
mode:
authorJoyee Cheung <joyeec9h3@gmail.com>2017-01-16 02:59:13 +0800
committerJoyee Cheung <joyeec9h3@gmail.com>2017-01-31 03:03:57 +0800
commit60d77bd514d3dc65cfbb64ebb8ae1f364e8bf8eb (patch)
tree7090c026e7b5cdb9550d18be604e2d375a318800 /benchmark/_benchmark_progress.js
parentca3d131bd42afa0c68be6aeb27623d53eae547a1 (diff)
downloadandroid-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.js120
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;