UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

119 lines 5.17 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const assert_1 = require("../util/assert"); const files_1 = require("../util/files"); const log_1 = require("../util/log"); const parallel_1 = require("../util/parallel"); const script_1 = require("./common/script"); const options = (0, script_1.processCommandLineArgs)('benchmark', [], { subtitle: 'Slice given files with additional benchmark information', examples: [ '{italic example-folder/}', '{bold --help}' ] }); if (options.input.length === 0) { console.error('No input files given. Nothing to do. See \'--help\' if this is an error.'); process.exit(0); } const numberRegex = /^\d+$/; (0, assert_1.guard)(options.slice === 'all' || options.slice === 'no' || numberRegex.test(options.slice), 'slice must be either all, no, or a number'); (0, assert_1.guard)(options.runs === undefined || options.runs > 0, 'runs must be greater than zero'); function removeIfExists(summarizedRaw) { if (fs_1.default.existsSync(summarizedRaw)) { console.log(`Removing existing ${summarizedRaw}`); try { fs_1.default.rmSync(summarizedRaw, { recursive: true }); } catch { log_1.log.error('failure in cleanup'); } } } async function benchmark() { removeIfExists(options.output); fs_1.default.mkdirSync(options.output, { recursive: true }); console.log(`Storing output in ${options.output}`); console.log(`Using ${options.parallel} parallel executors`); // we do not use the limit argument to be able to pick the limit randomly const files = []; const firstFile = options.input[0]; // Check whether input is single JSON file containing a list of paths if (options.input.length === 1 && fs_1.default.statSync(firstFile).isFile() && firstFile.endsWith('.json')) { console.log('Input is a single JSON file. Assuming it contains a list of files to process'); const content = fs_1.default.readFileSync(firstFile, 'utf8'); const paths = JSON.parse(content); const baseDir = findCommonBaseDir(paths); await collectFiles(files, paths, () => baseDir); } else { await collectFiles(files, options.input, (p) => p); } if (options.limit) { log_1.log.info(`limiting to ${options.limit} files`); // shuffle and limit files.sort(() => Math.random() - 0.5); } const limit = options.limit ?? files.length; const verboseAdd = options.verbose ? ['--verbose'] : []; const args = files.map((f, i) => [ '--input', f.request.content, '--file-id', `${i}`, '--output', path_1.default.join(options.output, path_1.default.relative(f.baseDir, `${f.request.content}.json`)), '--slice', options.slice, ...verboseAdd, '--parser', options.parser, ...(options['enable-pointer-tracking'] ? ['--enable-pointer-tracking'] : []), '--max-slices', `${options['max-file-slices']}`, ...(options.threshold ? ['--threshold', `${options.threshold}`] : []), '--sampling-strategy', options['sampling-strategy'], ]); const runs = options.runs ?? 1; for (let i = 1; i <= runs; i++) { console.log(`Run ${i} of ${runs}`); const pool = new parallel_1.LimitedThreadPool(`${__dirname}/benchmark-helper-app`, // we reverse here "for looks", since the helper pops from the end, and we want file ids to be ascending :D args.map(a => [...a, '--run-num', `${i}`]).reverse(), limit, options.parallel, options['per-file-time-limit']); await pool.run(); const stats = pool.getStats(); console.log(`Run ${i} of ${runs}: Benchmarked ${stats.counter} files, skipped ${stats.skipped.length} files due to errors`); } } /** * Collect all R files from the given paths. * * @param files - list of files to append to * @param paths - list of paths to search for R files * @param getBaseDir - function to get the base directory of a path */ async function collectFiles(files, paths, getBaseDir) { for (const input of paths) { for await (const file of (0, files_1.allRFiles)(input)) { files.push({ request: file, baseDir: getBaseDir(input) }); } } } /** * Find the common base directory of a list of paths. * * @param paths - list of paths * @returns the common base directory */ function findCommonBaseDir(paths) { const baseDirs = paths.map(f => path_1.default.dirname(f)); return baseDirs.reduce((acc, dir) => { const split = dir.split(path_1.default.sep); const accSplit = acc.split(path_1.default.sep); let i = 0; while (i < split.length && i < accSplit.length && split[i] === accSplit[i]) { i++; } return split.slice(0, i).join(path_1.default.sep); }, baseDirs[0]); } void benchmark(); //# sourceMappingURL=benchmark-app.js.map