From 793d61499b4ab53cdfdd3b81b9faf9f36b77bae8 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Thu, 25 May 2017 07:15:55 +0800 Subject: [PATCH] report timing breakdown (#2000) fix corner cases with `sourceMap` fixes #1998 --- README.md | 2 +- bin/uglifyjs | 14 ++++++++------ lib/minify.js | 47 +++++++++++++++++++++++++++++++++++------------ test/benchmark.js | 9 ++------- test/jetstream.js | 2 +- 5 files changed, 47 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 45c95e3a..47012c11 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ a double dash to prevent input files being used as option arguments: the source map. `url` If specified, path to the source map to append in `//# sourceMappingURL`. - --stats Display operations run time on STDERR. + --timings Display operations run time on STDERR. --toplevel Compress and/or mangle variables in top level scope. --verbose Print diagnostic messages. --warn Print warning messages. diff --git a/bin/uglifyjs b/bin/uglifyjs index 822e9266..8ea7d16b 100755 --- a/bin/uglifyjs +++ b/bin/uglifyjs @@ -39,7 +39,7 @@ program.option("--keep-fnames", "Do not mangle/drop function names. Useful for c program.option("--name-cache ", "File to hold mangled name mappings."); program.option("--self", "Build UglifyJS as a library (implies --wrap UglifyJS)"); program.option("--source-map [options]", "Enable source map/specify source map options.", parse_source_map()); -program.option("--stats", "Display operations run time on STDERR.") +program.option("--timings", "Display operations run time on STDERR.") program.option("--toplevel", "Compress and/or mangle variables in toplevel scope."); program.option("--verbose", "Print diagnostic messages."); program.option("--warn", "Print warning messages."); @@ -115,10 +115,10 @@ if (program.output == "ast") { }; } if (program.parse) { - if (program.parse.acorn || program.parse.spidermonkey) { - if (program.sourceMap) fatal("ERROR: inline source map only works with built-in parser"); - } else { + if (!program.parse.acorn && !program.parse.spidermonkey) { options.parse = program.parse; + } else if (program.sourceMap && program.sourceMap.content == "inline") { + fatal("ERROR: inline source map only works with built-in parser"); } } var convert_path = function(name) { @@ -172,7 +172,7 @@ function run() { UglifyJS.AST_Node.warn_function = function(msg) { console.error("WARN:", msg); }; - if (program.stats) program.stats = Date.now(); + if (program.timings) options.timings = true; try { if (program.parse) { if (program.parse.acorn) { @@ -259,7 +259,9 @@ function run() { return value instanceof UglifyJS.Dictionary ? value.toObject() : value; })); } - if (program.stats) console.error("Elapsed:", Date.now() - program.stats); + if (result.timings) for (var phase in result.timings) { + console.error("- " + phase + ": " + result.timings[phase].toFixed(3) + "s"); + } } function fatal(message) { diff --git a/lib/minify.js b/lib/minify.js index a827930a..16f5b189 100644 --- a/lib/minify.js +++ b/lib/minify.js @@ -30,9 +30,6 @@ function set_shorthand(name, options, keys) { function minify(files, options) { var warn_function = AST_Node.warn_function; try { - if (typeof files == "string") { - files = [ files ]; - } options = defaults(options, { compress: {}, ie8: false, @@ -41,10 +38,14 @@ function minify(files, options) { output: {}, parse: {}, sourceMap: false, + timings: false, toplevel: false, warnings: false, wrap: false, }, true); + var timings = options.timings && { + start: Date.now() + }; set_shorthand("ie8", options, [ "compress", "mangle", "output" ]); set_shorthand("keep_fnames", options, [ "compress", "mangle" ]); set_shorthand("toplevel", options, [ "compress", "mangle" ]); @@ -75,10 +76,14 @@ function minify(files, options) { warnings.push(warning); }; } + if (timings) timings.parse = Date.now(); var toplevel; if (files instanceof AST_Toplevel) { toplevel = files; } else { + if (typeof files == "string") { + files = [ files ]; + } options.parse = options.parse || {}; options.parse.toplevel = null; for (var name in files) { @@ -95,19 +100,23 @@ function minify(files, options) { if (options.wrap) { toplevel = toplevel.wrap_commonjs(options.wrap); } - if (options.compress) { - toplevel.figure_out_scope(options.mangle); - toplevel = new Compressor(options.compress).compress(toplevel); - } + if (timings) timings.scope1 = Date.now(); + if (options.compress) toplevel.figure_out_scope(options.mangle); + if (timings) timings.compress = Date.now(); + if (options.compress) toplevel = new Compressor(options.compress).compress(toplevel); + if (timings) timings.scope2 = Date.now(); + if (options.mangle) toplevel.figure_out_scope(options.mangle); + if (timings) timings.mangle = Date.now(); if (options.mangle) { - toplevel.figure_out_scope(options.mangle); base54.reset(); toplevel.compute_char_frequency(options.mangle); toplevel.mangle_names(options.mangle); - if (options.mangle.properties) { - toplevel = mangle_properties(toplevel, options.mangle.properties); - } } + if (timings) timings.properties = Date.now(); + if (options.mangle && options.mangle.properties) { + toplevel = mangle_properties(toplevel, options.mangle.properties); + } + if (timings) timings.output = Date.now(); var result = {}; if (options.output.ast) { result.ast = toplevel; @@ -123,7 +132,9 @@ function minify(files, options) { root: options.sourceMap.root }); if (options.sourceMap.includeSources) { - for (var name in files) { + if (files instanceof AST_Toplevel) { + throw new Error("original source content unavailable"); + } else for (var name in files) { options.output.source_map.get().setSourceContent(name, files[name]); } } @@ -142,6 +153,18 @@ function minify(files, options) { } } } + if (timings) { + timings.end = Date.now(); + result.timings = { + parse: 1e-3 * (timings.scope1 - timings.parse), + scope: 1e-3 * (timings.compress - timings.scope1 + timings.mangle - timings.scope2), + compress: 1e-3 * (timings.scope2 - timings.compress), + mangle: 1e-3 * (timings.properties - timings.mangle), + properties: 1e-3 * (timings.output - timings.properties), + output: 1e-3 * (timings.end - timings.output), + total: 1e-3 * (timings.end - timings.start) + } + } if (warnings.length) { result.warnings = warnings; } diff --git a/test/benchmark.js b/test/benchmark.js index d7b0263f..e27ed2c3 100644 --- a/test/benchmark.js +++ b/test/benchmark.js @@ -9,7 +9,7 @@ var args = process.argv.slice(2); if (!args.length) { args.push("-mc"); } -args.push("--stats"); +args.push("--timings"); var urls = [ "https://code.jquery.com/jquery-3.2.1.js", "https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.js", @@ -29,12 +29,7 @@ function done() { var info = results[url]; console.log(); console.log(url); - var elapsed = 0; - console.log(info.log.replace(/Elapsed: ([0-9]+)\s*/g, function(match, time) { - elapsed += 1e-3 * parseInt(time); - return ""; - })); - console.log("Run-time:", elapsed.toFixed(3), "s"); + console.log(info.log); console.log("Original:", info.input, "bytes"); console.log("Uglified:", info.output, "bytes"); console.log("SHA1 sum:", info.sha1); diff --git a/test/jetstream.js b/test/jetstream.js index 56da7ad8..4f13a281 100644 --- a/test/jetstream.js +++ b/test/jetstream.js @@ -14,7 +14,7 @@ if (typeof phantom == "undefined") { if (!args.length) { args.push("-mc"); } - args.push("--stats"); + args.push("--timings"); var child_process = require("child_process"); try { require("phantomjs-prebuilt"); -- 2.34.1