mirror of https://github.com/lukechilds/node.git
Browse Source
* 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>v7.x
Joyee Cheung
8 years ago
committed by
Evan Lucas
6 changed files with 187 additions and 24 deletions
@ -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; |
Loading…
Reference in new issue