【问题标题】:Why does minified or obfuscated JavaScript perform worse than uncompressed code?为什么缩小或混淆的 JavaScript 比未压缩的代码执行得更差?
【发布时间】:2013-03-17 08:21:26
【问题描述】:

我遇到了this performance report 使用各种压缩器和混淆器压缩的 JavaScript 代码。令人惊讶的是,除了 Closure 高级模式之外,在大多数情况下,所有其他压缩器输出的代码都比未压缩的代码执行得更差。我们该如何解释?

向下滚动到page 的末尾以查看报告。以下是截图:

传奇:

  • 蓝色 - YUI 压缩机
  • 红色 - 关闭(高级模式)
  • 橙色 - 关闭(基本模式)
  • 绿色 - JS Min
  • 紫色 - JS 打包器
  • 浅蓝色 - UglifyJS
  • 粉色 - 未压缩代码

【问题讨论】:

  • 这不是真正的重复 @Barmar - 是的,它是关于混淆的,但它谈论的是 Java 和 C#,而不是 JavaScript。
  • 我不确定操作对等秒是否真的是一个很好的指标......当然,这只是表明哪个混淆器有利于最简单的操作,并没有说明整个代码的速度......
  • @Ozzy,JS 中的混​​淆/压缩更多是为了减少需要发送到浏览器的数据量。这使得页面加载速度更快,当然你也会关心它是否运行得更快。
  • @DavidMcMullin,这通过压缩文件而不是混淆来更有效地完成,这可能会引入错误。 yuiblog.com/blog/2006/03/06/minification-v-obfuscation
  • @Ozzy 这不是一个或另一个问题,两者都将产生最小的文件大小和最快的加载时间。

标签: javascript performance obfuscation minify


【解决方案1】:

首先让我扮演魔鬼的拥护者:代码实际上并没有“执行”任何事情(我的意思是没什么严重的,除了 JS Packer)。它本质上是函数、对象和属性的定义。

JS Packer 不生成 JavaScript 代码,而是生成必须在运行时解压缩的压缩文本。这就是为什么它要慢得多。使用高级优化的 Google Closure 会尽可能替换标识符。所以在解析脚本的时候已经有了性能优势。

也就是说,为了代码大小而牺牲性能是可能的。一个示例是将truefalse 替换为!0!1。不过,这取决于 JavaScript 引擎。它可以在第一次调用之前由引擎优化,之后,在一些调用之后,永远......谁知道;)

新发现

与此同时,我进行了一些分析,并意识到我忘记了一件事:垃圾收集。这种影响足以解释脚本和浏览器之间的一些差异(不同的引擎!)。

将这一点与代码没有做太多事情的事实结合起来,你就有了一些东西。在一项测试中,未压缩的垃圾收集 CPU 时间约为 3%,JSMin 的垃圾收集时间约为 9%(!)。这意味着几乎相同的代码会得到完全不同的结果。

更新的发现

当您首先运行 JSMin 时,它比未压缩的要快。我尝试了几次,总是得到相同的结果。这证实了之前的发现。我现在非常有信心,我们找到了解决方案。

【讨论】:

  • +1 表示代码不做任何事情。唯一重要的基准是您自己的。
  • 当然,代码实际上并没有“执行”任何操作。所以它不能代表一个好的基准。尽管如此,为什么缩小的代码对于这个特定的测试表现更差? JSMin,尤其是simply omits some whitespace。那么为什么它的表现会更差呢?
  • 甚至有 JSMin 的性能与未压缩版本相当的结果。但是 JSMin 的表现对我来说似乎也很奇怪。除此之外,我们必须考虑 3 个问题: 1. 解析:构建 AST 需要花费时间,尤其是对于这个脚本。 2. 这一切都取决于 JavaScript 引擎。结果差异很大。 3. 框架本身,或者它进行基准测试的方式,可能这种的情况产生影响。我不这么认为,但我不能肯定地说。
  • 我担心要解释每个差异都需要浏览器供应商的参与。或者检查 JS 引擎的源代码 ;)
【解决方案2】:

您似乎无意中将缩小与混淆混淆了。

为了理解这两种技术,我将分别进行解释。

缩小是缩小源文件大小并将其制成旨在提高机器可读性的格式的过程。这是通过 (a) 删除 cmets 和不必要的空格,并可能 (b) 用简单的增量变量名替换变量名来完成的,这些变量名通常以一个字符开头。生成的代码仍然与原始代码功能相同,但理论上浏览器解析和编译速度更快。

混淆是一种修改代码以使其不再被识别为原始源代码的技术,通常用于阻止对专有代码进行逆向工程。某些更改可能会对它们产生开销,例如代码可能会在运行时被加密然后再次解密。也就是说,代码混淆器通常也会通过缩小输出来完成工作。

尽管可以将缩小视为一种粗略的混淆形式,但通常执行此类过程更多是出于性能和/或带宽目的。

【讨论】:

    【解决方案3】:

    是的,混淆可能会导致一些性能问题,但压缩代码的性能并不比未压缩的代码差。事实上,压缩后的代码比未压缩的代码执行得更好。这是因为,minfied 代码具有更短的变量/函数名称,因此对分配的内存空间的引用调用更容易!

    【讨论】:

      猜你喜欢
      • 2021-11-28
      • 2012-12-09
      • 2011-10-23
      • 1970-01-01
      • 2018-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多