为什么使用Closure Compiler坚持增加更多的字节?(Why does Closure C

2019-07-29 01:19发布

如果我给关闭编译器是这样的:

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

据“编译”是这样的:

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

现在,你可以告诉,这是更大的。 是否有任何理由关闭编译器是这样做?

Answer 1:

认为这是发生了什么事情,但我不能肯定...

使逗号的插入的代码是tryMinimizeStringArrayLiteral在PeepholeSubstituteAlternateSyntax.java 。

该方法包含有可能具有低的字符列表霍夫曼编码 ,并因此优选比其它字符分割上。 你可以看到这样的结果,如果你尝试这样的事:

"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)

编译器将取代你尝试用一个它认为有利于分裂的性格。 它通过遍历字符串的字符和发现并不在字符串中可能发生的最有利的分裂性格:

// 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);
  //...
}

在上面的代码段可以看到字符数组编译声称是最佳分裂上。 逗号是第一个(这就是为什么在我上面的空间例如,空间已用逗号替换)。

我相信,在拆分的字符串为空字符串可能仅仅是一个疏忽的情况下逗号的插入。 似乎没有成为该情况下的任意特殊处理,所以它像对待任何其他split呼叫和每个字符加入了与从上述代码段中所示的阵列的第一个适当的字符。


如何与编译器处理的另一个例子split方法:

"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

这一次,由于原字符串已经包含逗号(,我们不希望拆就逗号字符),逗号不能从低霍夫曼编码的字符数组中选择,所以接下来最好的选择是选择(空间)。


更新

经过一些进一步研究这个,这绝不是一个错误。 这种行为实际上是由设计,在我看来这是一个非常聪明的小优化,当你记住的是,Closure编译器往往有利于在大小编译代码的速度

上面我提到霍夫曼编码几次。 霍夫曼编码算法,解释的很简单地说,权重分配给出现的文本将被编码的每个字符。 该权重是基于与每个字符出现的频率。 这些频率用来建立一个二进制树,在根中最常见的字符。 这意味着,最常见的字符是更快地解码,因为它们更接近树的根。

而且,由于霍夫曼算法是gzip的DEFLATE算法的很大一部分。 所以,如果你的Web服务器被配置为使用gzip的,你的用户将受益于这个聪明的优化。



Answer 2:

此问题已固定在2012年4月20日查看修订: https://code.google.com/p/closure-compiler/source/detail?r=1267364f742588a835d78808d0eef8c9f8ba8161



Answer 3:

讽刺的是, split的编译代码无关与split的来源。 考虑:

Source  : a = ["0","1","2","3","4","5"]
Compiled: a="0,1,2,3,4,5".split(",")

在这里, split只是代表长阵列(时间足够长,报价+逗号的总和长于方式split(","")所以,这是怎么回事在你的榜样?首先,编译器看到一个字符串功能应用到一个常数,对其进行评估的时候了:

'0123456789'.split('') => ["0","1","2","3","4","5","6","7","8","9"]

在以后的某个点上,产生输出时,编译器认为这阵列是“长”和在上述“分离”的形式将它写入:

["0","1","2","3","4","5","6","7","8","9"] => "0,1,2,3,4,5,6,7,8,9".split(",")

请注意,所有的信息split('')在源已经失去了在这一点上。

如果源串均短,这将在阵列阵列形式产生,而无需额外的分割:

Source  : a = '0123'.split('')
Compiled: a=["0","1","2","3"]


文章来源: Why does Closure Compiler insist on adding more bytes?