简体   繁体   中英

How does Closure Compiler use type information to compile to faster JavaScript?

Google's Closure Compiler compiles to more efficient JavaScript. I can imagine a few simple examples, such as Closure Compiler reducing the call stack by calling functions directly or replacing constants with literals. But the documentation goes further, saying,

"The Closure Compiler can use data type information about JavaScript variables to provide enhanced optimization and warnings."

My understanding was that typed languages had two benefits: 1) type checking can catch errors during compilation--I can see how Closure Compiler could simulate this behavior--and 2) the program actually executes faster because it is compiled to another language (say Java to Java bytecode). With Closure Compiler, the output is still JavaScript. How can it be optimized based on type information?

One example is the disambiguateProperties feature, described at http://closuretools.blogspot.com/2011/01/property-by-any-other-name-part-3.html

As the post describes, this allows the compiler to pick shorter property names. It also allows the compiler to eliminate more dead code. Suppose you call x.foo() in your code, and there are two different types that both have a foo method:

X1.prototype.foo = function() {
  // Lots and lots of code...
};


X2.prototype.foo = function() {
  // Lots and lots of code...
};

If the compiler doesn't know what type x is, it has to keep both long foo methods in the code, even though one of them might never be called. If it knows that x is of type X1 , then it'll rename the methods to X1$foo and X2$foo (or something like that). Then, it can see that X2$foo is never called, so it removes it from the compiled code. This means less code to download and parse, so it can make the page feel like it loads a lot faster, and one less function that the JS interpreter has to keep in memory.

The type based "optimizations" in Closure Compiler isn't purely optimizations on their own. In compiler terms, it strictly exposes opportunities for other optimizations .

Here is an example I constructed on http://closure-compiler.appspot.com/home

// ==ClosureCompiler==
// @compilation_level ADVANCED_OPTIMIZATIONS
// @use_types_for_optimization true
// @formatting pretty_print
// @output_file_name default.js
// ==/ClosureCompiler==

/** @constructor */
function X(){}
X.prototype.foo = function() {alert("X")};

/** @constructor */
function Y(){}
Y.prototype.foo = function() {alert("Y")};

window.i = new X();
window.j = new Y();


/**
 * @param {!X} x
 */
window.keep = function(x) {
 x.foo();
}

If you toggle *use_types_for_optimization* true to false , you will noticed that the alert doesn't get inlined anymore. Notice that without the type information, it is impossible to tell the callers of keep is always X .

In that sense, the type information helped contributed to inlining.

Hope that helps.

The documentation doesn't state anything about creating code that executes faster. The compiler's focus has always been checking and code size. While it can generate code that runs faster (usually by removing indirection), it can also create code that runs slower due by creating code that violates some optimization criteria for the JS VMs (creating function that are too large, etc).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM