UNPKG

8.69 kBJavaScriptView Raw
1"use strict";
2
3var _index = _interopRequireDefault(require("./serializer/index.js"));
4
5var _construct_realm = _interopRequireDefault(require("./construct_realm.js"));
6
7var _globals = _interopRequireDefault(require("./globals.js"));
8
9var _invariant = _interopRequireDefault(require("./invariant.js"));
10
11function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
13function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
14
15function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
16
17let chalk = require("chalk");
18
19let jsdom = require("jsdom");
20
21let zlib = require("zlib");
22
23let fs = require("fs");
24
25let vm = require("vm");
26
27function getTime() {
28 let stamp = process.hrtime();
29 return (stamp[0] * 1e9 + stamp[1]) / 1e6;
30}
31
32function exec(_code, compatibility) {
33 let code = _code;
34 let sandbox = {
35 setTimeout: setTimeout,
36 setInterval: setInterval,
37 console: {
38 error() {},
39
40 log(s) {
41 console.log(s);
42 }
43
44 }
45 };
46 let beforeCode = "var global = this; ";
47 let afterCode = `// At the end of the script, Node tries to clone the 'this' Object (global) which involves executing all getters on it.
48// To avoid executing any more code (which could affect timing), we just set all globals to undefined (hoping that doesn't take too long).
49Object.getOwnPropertyNames(global).forEach(function(name){ if (name !== "Object" && name !== "global") global[name] = undefined; });`;
50
51 if (compatibility === "browser") {
52 beforeCode += "var window = this; var self = this; ";
53 let window = jsdom.jsdom({}).defaultView;
54 sandbox.window = window;
55 sandbox.document = window.document;
56 sandbox.navigator = window.navigator;
57 sandbox.location = window.location;
58 }
59
60 if (compatibility === "jsc-600-1-4-17") {
61 beforeCode += "delete global.clearInterval; delete global.clearImmediate; delete global.clearTimeout; delete global.setImmediate; delete Object.assign;";
62 }
63
64 code = `${beforeCode} ${code}; // keep newline here as code may end with comment
65${afterCode}`;
66 let start = getTime();
67 let script = new vm.Script(code, {
68 cachedDataProduced: false
69 });
70 let executedStart = getTime();
71 script.runInNewContext(sandbox);
72 let executedEnd = getTime();
73 return {
74 raw: code.length,
75 gzip: zlib.gzipSync(code).length,
76 executed: executedEnd - executedStart,
77 compiled: executedStart - start,
78 total: executedEnd - start
79 };
80}
81
82function line(type, code, compatibility, moreOut = {}, compareStats = undefined) {
83 let stats = exec(code, compatibility);
84
85 function wrapTime(key) {
86 return wrap(key, ms => `${ms.toFixed(2)}ms`, "faster", "slower");
87 }
88
89 function wrapSize(key) {
90 return wrap(key, function (b) {
91 let kilobytes = Math.round(b / 1000);
92
93 if (kilobytes > 1000) {
94 return `${(kilobytes / 1000).toFixed(2)}MB`;
95 } else {
96 return `${kilobytes}KB`;
97 }
98 }, "smaller", "bigger");
99 }
100
101 function wrap(key, format, positive, negative) {
102 if (compareStats) {
103 let before = compareStats[key];
104 let after = stats[key];
105 let factor;
106
107 if (after < before) {
108 factor = chalk.green(`${(before / after).toFixed(2)}x ${positive}`);
109 } else {
110 factor = chalk.red(`${(after / before).toFixed(2)}x ${negative}`);
111 }
112
113 return `${format(after)} ${factor}`;
114 } else {
115 return format(stats[key]);
116 }
117 }
118
119 let out = _objectSpread({
120 "VM Total Time": wrapTime("total"),
121 "VM Compile Time": wrapTime("compiled"),
122 "VM Execution Time": wrapTime("executed"),
123 "Raw Code Size": wrapSize("raw"),
124 "Gzip Code Size": wrapSize("gzip")
125 }, moreOut);
126
127 console.log(chalk.bold(type));
128
129 for (let key in out) {
130 console.log(` ${chalk.bold(key)} ${out[key]}`);
131 }
132
133 return stats;
134}
135
136function dump(name, raw, min = raw, compatibility = "browser", outputFilename) {
137 console.log(chalk.inverse(name));
138 let beforeStats = line("Before", min, compatibility);
139 let start = Date.now();
140 let realm = (0, _construct_realm.default)({
141 serialize: true,
142 compatibility
143 });
144 (0, _globals.default)(realm);
145 let serializer = new _index.default(realm);
146 let sources = [{
147 filePath: name,
148 fileContents: raw
149 }];
150 let serialized = serializer.init(sources);
151
152 if (!serialized) {
153 process.exit(1);
154 (0, _invariant.default)(false);
155 }
156
157 let code = serialized.code;
158 let total = Date.now() - start;
159 const isValidOutputFilename = outputFilename !== undefined && outputFilename !== "";
160
161 if (code.length >= 1000 || isValidOutputFilename) {
162 let filename = outputFilename !== undefined ? outputFilename : name + "-processed.js";
163 console.log(`Prepacked source code written to ${filename}.`);
164 fs.writeFileSync(filename, code);
165 }
166
167 line("After", code, compatibility, {
168 "Prepack Compile Time": `${total}ms`
169 }, beforeStats);
170
171 if (code.length <= 1000 && !isValidOutputFilename) {
172 console.log("+++++++++++++++++ Prepacked source code");
173 console.log(code);
174 console.log("=================");
175 }
176}
177
178let args = Array.from(process.argv);
179args.splice(0, 2);
180let inputFilename;
181let outputFilename;
182let compatibility;
183
184while (args.length) {
185 let arg = args[0];
186 args.shift();
187
188 if (arg === "--out") {
189 arg = args[0];
190 args.shift();
191 outputFilename = arg;
192 } else if (arg === "--compatibility") {
193 arg = args[0];
194 args.shift();
195
196 if (arg !== "jsc-600-1-4-17") {
197 console.error(`Unsupported compatibility: ${arg}`);
198 process.exit(1);
199 } else {
200 compatibility = arg;
201 }
202 } else if (arg === "--help") {
203 console.log("Usage: benchmarker.js [ --out output.js ] [ --compatibility jsc ] [ -- | input.js ]");
204 } else if (!arg.startsWith("--")) {
205 inputFilename = arg;
206 } else {
207 console.error(`Unknown option: ${arg}`);
208 process.exit(1);
209 }
210}
211
212if (!inputFilename) {
213 console.error("Missing input file.");
214 process.exit(1);
215} else {
216 let input = fs.readFileSync(inputFilename, "utf8");
217 dump(inputFilename, input, input, compatibility, outputFilename);
218} //dump("helloWorld", "function hello() { return 'hello'; } function world() { return 'world'; } s = hello() + ' ' + world();");
219//dump("regex", "regex = /Facebook/i;");
220//dump("test", "try { new WeakSet().delete.call(0, {}); } catch (e) {console.log(e);}");
221//dump("test", "e = 'abcdef'.substr(1,2); ");
222//dump("test", "var s = 'Promise'; e = s[0];");
223//dump("test", "foo = function() { return [,0]; };");
224//dump("simple", "var foo = 5 * 5; var bar = [2, 3, 'yes']; var foo2 = null; var bar2 = undefined;");
225//dump("simple2", "function Foo() {} Foo.prototype.wow = function () {};");
226//dump("Date.now", "Date.now");
227//dump("Date.now", "this.foo = Date.now();");
228//dump("object recursion", "var obj = { yes: 'no' }; obj.bar = obj; var foo = [obj]; obj.foobar = foo;");
229//dump("intrinsic union", "var assign = Object.assign || function () {}; var obj = assign({ foo: 1 }, { bar: 2 });");
230
231/*dump(
232 "fbsdk",
233 fs.readFileSync(__dirname + "/../assets/fbsdk.js", "utf8")
234);*/
235
236/*dump(
237 "react",
238 fs.readFileSync(__dirname + "/../assets/react.js", "utf8"),
239 fs.readFileSync(__dirname + "/../assets/react.min.js", "utf8")
240);*/
241
242/*dump(
243 "immutable",
244 fs.readFileSync(__dirname + "/../assets/immutable.js", "utf8"),
245 fs.readFileSync(__dirname + "/../assets/immutable.min.js", "utf8")
246);*/
247
248/*dump(
249 "react-native-bundle",
250 fs.readFileSync(__dirname + "/../../examples/react-native-bundle/bundle.js", "utf8")
251);*/
252
253/*dump(
254 "lodash",
255 fs.readFileSync(require.resolve("lodash/lodash.js"), "utf8"),
256 fs.readFileSync(require.resolve("lodash/lodash.min.js"), "utf8")
257);*/
258
259/*dump(
260 "underscore",
261 fs.readFileSync(require.resolve("underscore"), "utf8"),
262 fs.readFileSync(require.resolve("underscore/underscore-min"), "utf8")
263);
264*/
265
266/*dump(
267 "ember",
268 fs.readFileSync("ember.prod.js", "utf8")
269);
270
271dump(
272 "jquery",
273 fs.readFileSync(require.resolve("jquery/dist/jquery.js"), "utf8"),
274 fs.readFileSync(require.resolve("jquery/dist/jquery.min.js"), "utf8")
275);
276
277dump(
278 "scrollin",
279 fs.readFileSync("scrollin.js", "utf8")
280);
281*/
282//# sourceMappingURL=benchmarker.js.map
\No newline at end of file