2017-01-15 18:59:13 +00:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
const readline = require('readline');
|
|
|
|
|
|
|
|
function pad(input, minLength, fill) {
|
2017-09-14 01:48:53 +00:00
|
|
|
const result = String(input);
|
|
|
|
const padding = fill.repeat(Math.max(0, minLength - result.length));
|
2017-04-17 01:01:12 +00:00
|
|
|
return `${padding}${result}`;
|
2017-01-15 18:59:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function fraction(numerator, denominator) {
|
2017-04-17 01:01:12 +00:00
|
|
|
const fdenominator = String(denominator);
|
2017-01-15 18:59:13 +00:00
|
|
|
const fnumerator = pad(numerator, fdenominator.length, ' ');
|
|
|
|
return `${fnumerator}/${fdenominator}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
function getTime(diff) {
|
|
|
|
const time = Math.ceil(diff[0] + diff[1] / 1e9);
|
2017-02-08 08:27:35 +00:00
|
|
|
const hours = pad(Math.floor(time / 3600), 2, '0');
|
|
|
|
const minutes = pad(Math.floor((time % 3600) / 60), 2, '0');
|
|
|
|
const seconds = pad((time % 3600) % 60, 2, '0');
|
2017-01-15 18:59:13 +00:00
|
|
|
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.
|
|
|
|
// Number of configurations already run for the current file.
|
|
|
|
this.completedConfig = 0;
|
|
|
|
// Total number of configurations for the current file
|
|
|
|
this.scheduledConfig = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2017-07-28 00:52:39 +00:00
|
|
|
completeConfig() {
|
2017-01-15 18:59:13 +00:00
|
|
|
this.completedConfig++;
|
|
|
|
this.updateProgress();
|
|
|
|
}
|
|
|
|
|
2017-07-28 00:52:39 +00:00
|
|
|
completeRun() {
|
2017-01-15 18:59:13 +00:00
|
|
|
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;
|
2017-06-24 03:52:07 +00:00
|
|
|
const completedRunsForFile =
|
|
|
|
finished ? runsPerFile : completedRuns % runsPerFile;
|
2017-01-15 18:59:13 +00:00
|
|
|
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;
|
2017-06-24 03:52:07 +00:00
|
|
|
return `[${getTime(diff)}|% ${percent}| ` +
|
|
|
|
`${fraction(completedFiles, scheduledFiles)} files | ` +
|
|
|
|
`${fraction(completedRunsForFile, runsPerFile)} runs | ` +
|
|
|
|
`${fraction(completedConfig, scheduledConfig)} configs]: ` +
|
|
|
|
`${caption} `;
|
2017-01-15 18:59:13 +00:00
|
|
|
}
|
|
|
|
|
2017-07-28 00:52:39 +00:00
|
|
|
updateProgress() {
|
2017-01-15 18:59:13 +00:00
|
|
|
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;
|