Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Closure Compiler insist on adding more bytes?

Tags:

If I give Closure Compiler something like this:

window.array = '0123456789'.split('');

It "compiles" it to this:

window.array="0,1,2,3,4,5,6,7,8,9".split(",");

Now as you can tell, that's bigger. Is there any reason why Closure Compiler is doing this?

like image 643
qwertymk Avatar asked Apr 18 '12 13:04

qwertymk


People also ask

What is the function of closure compiler?

The Closure Compiler is a tool for making JavaScript download and run faster. Instead of compiling from a source language to machine code, it compiles from JavaScript to better JavaScript. It parses your JavaScript, analyzes it, removes dead code and rewrites and minimizes what's left.

Why use google Closure?

The Closure Compiler compiles JavaScript into compact, high-performance code. The compiler removes dead code and rewrites and minimizes what's left so that it downloads and runs quickly. It also checks syntax, variable references, and types, and warns about common JavaScript pitfalls.

Which of the following are the three compilation levels that can be applied to the JavaScript code to define the degree of compression and optimization required?

The value of this parameter indicates the degree of compression and optimization to apply to your JavaScript. There are three possible compilation levels: WHITESPACE_ONLY , SIMPLE_OPTIMIZATIONS , and ADVANCED_OPTIMIZATIONS .


2 Answers

I think this is what's going on, but I am by no means certain...

The code that causes the insertion of commas is tryMinimizeStringArrayLiteral in PeepholeSubstituteAlternateSyntax.java.

That method contains a list of characters that are likely to have a low Huffman encoding, and are therefore preferable to split on than other characters. You can see the result of this if you try something like this:

"a b c d e f g".split(" "); //Uncompiled, split on spaces
"a,b,c,d,e,f,g".split(","); //Compiled, split on commas (same size)

The compiler will replace the character you try to split on with one it thinks is favourable. It does so by iterating over the characters of the string and finding the most favourable splitting character that does not occur within the string:

// These delimiters are chars that appears a lot in the program therefore
// probably have a small Huffman encoding.
NEXT_DELIMITER: for (char delimiter : new char[]{',', ' ', ';', '{', '}'}) {
  for (String cur : strings) {
    if (cur.indexOf(delimiter) != -1) {
      continue NEXT_DELIMITER;
    }
  }
  String template = Joiner.on(delimiter).join(strings);
  //...
}

In the above snippet you can see the array of characters the compiler claims to be optimal to split on. The comma is first (which is why in my space example above, the spaces have been replaced by commas).

I believe the insertion of commas in the case where the string to split on is the empty string may simply be an oversight. There does not appear to be any special treatment of this case, so it's treated like any other split call and each character is joined with the first appropriate character from the array shown in the above snippet.


Another example of how the compiler deals with the split method:

"a,;b;c;d;e;f;g".split(";"); //Uncompiled, split on semi-colons
"a, b c d e f g".split(" "); //Compiled, split on spaces

This time, since the original string already contains a comma (and we don't want to split on the comma character), the comma can't be chosen from the array of low-Huffman-encoded characters, so the next best choice is selected (the space).


Update

Following some further research into this, it is definitely not a bug. This behaviour is actually by design, and in my opinion it's a very clever little optimisation, when you bear in mind that the Closure compiler tends to favour the speed of the compiled code over size.

Above I mentioned Huffman encoding a couple of times. The Huffman coding algorithm, explained very simply, assigns a weight to each character appearing the the text to be encoded. The weight is based on the frequency with which each character appears. These frequencies are used to build a binary tree, with the most common character at the root. That means the most common characters are quicker to decode, since they are closer to the root of the tree.

And since the Huffman algorithm is a large part of the DEFLATE algorithm used by gzip. So if your web server is configured to use gzip, your users will be benefiting from this clever optimisation.

like image 54
James Allardice Avatar answered Sep 21 '22 05:09

James Allardice


This issue was fixed on Apr 20, 2012 see revision: https://code.google.com/p/closure-compiler/source/detail?r=1267364f742588a835d78808d0eef8c9f8ba8161

like image 24
John Avatar answered Sep 20 '22 05:09

John