【问题标题】:Commenting interpreted code and performance评论解释代码和性能
【发布时间】:2011-12-05 13:37:23
【问题描述】:

我总是(很好地尝试)评论我的代码。我已将服务器配置为在交付前删除那些 cmets/额外的空白。在实时系统代码 (Javascript/php) 中不要使用 cmets 会更好吗?从而减少这种开销或删除或解释?

如果是这样,我怎么能把蛋糕也吃掉?

【问题讨论】:

  • 听起来您已经可以使用它了。究竟是什么问题?
  • 我仍然会注释我的代码,并在交付时使用缩小器来缩小和删除 cmets。
  • 相关,请参阅stackoverflow.com/questions/2731022/… - 它并不完全适用于您提到的语言,因为它们不会缓存字节码编译的结果。但是在(非常快的)词法分析阶段之后它们不存在的观点仍然存在。不用说,即使这个开销在微基准测试中是可测量的,因此丢掉好的 cmets 也是疯狂的。

标签: php javascript comments


【解决方案1】:

对于 PHP,没有区别。您的 PHP 代码不会发送到浏览器。

对于 JavaScript,建议您缩小代码。这通过更改变量名称、删除空格以及删除所有 cmets 来减小其大小。有几个 online tools 可以做到这一点,并且它通常在您的 IDE 中可用。

无论您做什么,请在您处理代码的地方留下注释。不要从 PHP 中删除 cmets,也不要手动缩小 JS。

【讨论】:

  • 对于 PHP - 解析器肯定每次都需要查看 cmets 并跳过它们。即从光盘读取访问权限,处理以跳过它们。
  • @EdHeal 您是否在大型、知名和使用过的库中看到 cmets?是的你是。跳过 cmets 的成本可以忽略不计。
  • @EdHeal,任何对性能的影响都会非常小,以至于无法估量。如果您不相信我,请继续测试它。对于谁对此投反对票,请自行解释。
  • 对于 JavaScript,只建议压缩,因为文件必须由客户端下载——并且压缩版本的传输速度更快。但是对于 PHP 和 JavaScript,如果添加 cmets,解析器确实必须读取更多字节。然而,这是一个很小的开销。
  • -1,因为 OP 询问了性能——与浏览器或网络流量无关。在服务器端解释(跳过)cmets 仍有一些成本。问题是这样的:“一些”是多少。这个答案忽略了这个方面,这实际上是问题的要点。
【解决方案2】:

虽然一般假设是让 PHP 通过 cmets 进行咀嚼会导致 没有可测量的差异,但最好检查一下,不是吗?

(注意:按照常识,我们期望纯粹的请求处理、权限管理、流程控制、调度这个、委托那个、启动 PHP 运行时环境、管理各种缓存、摆弄资产文件、整个磁盘和网络 I/O 等等等等,哦,顺便说一句,也执行代码,所有这些加起来很可能远远超过任何大量的 cmets。)

所以我给了它一个非常简单的尝试,只是为了立即感受它。

1。设置

预测“评论影响”与neutrinos 一样难以检测,因此我特意做了一个稍微有点病态的设置,试图使差异可衡量,但仍不能过于不切实际。

我创建了两个文件。一个没有 cmets,只有大约 100 个字节,直截了当,no-comments.php

<?php
function task() {
    ++$GLOBALS;
    echo "[$GLOBALS] Lorem ipsum dolor sit amet cosectetur...\n";
}

另外,大约 60K(仅出于与堆管理相关的迷信而保持在 64K 以下)comments.php

<?php
/* ... some 30K comments ... */
// OK, that's something, but how about:
/* ... same 30K comments again ... (Phantomjs changelog, for the curious of you. :) ) */
// Finally, do something:
function task() {
    ++$GLOBALS; // Comments are cheap, so let me tell you how much I enjoyed this instead of properly declaring a counter. :)
    echo "[$GLOBALS] Lorem ipsum with a lot of comments...\n";
}

注意:这当然很可能会测试文件大小的实际影响,而不仅仅是 cmets,但这始终是“cmets(非)问题”的固有部分" 无论如何,我也想要 something 首先。也许即使那已经无法衡量了,对吧?

一般的想法是然后以各种方式循环 task(),从同一个 PHP 进程内部循环一点(或根本没有),从外部循环很多,通过单独的执行,强制重新解析,这是本实验唯一有趣的部分。

为了获得最快的结果,我做了一些 shell 运行

#!/bin/bash
for (( i = 0; i < 1000; i++ ))
do
   php comments.php  # <-- and another batch with "no-comments.php"
done

但结果证明这是不可靠的,因为增加循环次数会导致执行时间发生莫名其妙且不成比例的变化。我改用 PHP 运行器,运行更流畅:

#!/usr/bin/php
<?php
$t1 = microtime(true);
for ($i = 0; $i < 1000; ++$i ) {
        system("php comments.php"); // <-- and with "no-comments.php"
}
$t2 = microtime(true);
echo "Time: ", $t2 - $t1

对于 HTTP 运行,然后我添加了这个index.php

<?php
$GLOBALS = 0; // innovative use of a dull language feature ;)

$t1 = microtime(true);

require_once (isset($_GET['no']) ? 'no-' : '') . 'comments.php';

// Played a bit with looping here, but ended up leaving it out.
// for ($i = 0; $i < 3; ++$i) {
//      task();
//      echo '<br>';
// }

$t2 = microtime(true);
echo "<hr>Time: ",  number_format($t2 - $t1, 10);

注意:起初,不幸的是,我启用了 PHP 的 Zend Opcache,并浪费了很多时间试图理解结果...... ;-o 然后我当然禁用了缓存,并重复了 Web 测试(only)。

主机只是普通的 Debian、Apache2 和一些 PHP5(我猜它是 FPM——甚至没有费心检查,因为这应该与测试的主题正交(如果这不是真的,请纠正我) . 它实际上甚至可以通过减少无关的 PHP 启动开销来掩盖微小的注释解析时间来帮助揭示差异。)

2。结果 - 外壳:

运行 PHP-cli 出奇的慢,所以我很快就厌烦了,这两种变体只进行了 1000 次迭代的十几个循环。 (以秒为单位的结果。)

评论:

44.2015209198
39.710990905762
42.374881982803
36.29861998558
44.764121055603
38.85772395134
42.627450942993
38.342661142349
48.539611816406
39.784120082855
50.34646987915
47.782819032669
36.974604845047
45.692447900772

平均:42.592717

没有评论:

45.617978811264
43.397685050964
46.341667175293
44.246716976166
40.348230838776
43.048954963684
38.57627081871
50.429704189301
41.811543226242
35.755078077316
53.086957931519
31.751699924469
48.388355970383
49.540207862854

平均:43.738647

如你所见,这都是垃圾......但如果我们忽略环境波动,结论是使用更多的 cmets,它会让你的脚本更快! :)

3。结果 - HTTP、Zend Opcache 已启用:

(从 ab 输出中去除了一些噪音。)

评论:

ab -qd -n 10000 'http://.../comments/?yes'

Server Software:        Apache/2.4.10
Concurrency Level:      1
Time taken for tests:   3.158 seconds
Complete requests:      10000
Failed requests:        0
Non-2xx responses:      10000
Total transferred:      7120000 bytes
HTML transferred:       4620000 bytes
Requests per second:    3166.12 [#/sec] (mean)
Time per request:       0.316 [ms] (mean)
Transfer rate:          2201.45 [Kbytes/sec] received

没有评论:

ab -qd -n 10000 'http://.../comments/?no'

Server Software:        Apache/2.4.10
Concurrency Level:      1
Time taken for tests:   3.367 seconds
Complete requests:      10000
Failed requests:        0
Non-2xx responses:      10000
Total transferred:      7120000 bytes
HTML transferred:       4620000 bytes
Requests per second:    2969.95 [#/sec] (mean)
Time per request:       0.337 [ms] (mean)
Transfer rate:          2065.04 [Kbytes/sec] received

哇! :-o 就像 shell 运行一样! :) 好吧,不相信我的眼睛,我又重复了几次,直到它有意义... :) 看到了吗?这里:

Benchmarking ...<"NO COMMENTS">... (be patient).....done

Time taken for tests:   2.912 seconds
Total transferred:      7120000 bytes
HTML transferred:       4620000 bytes
Requests per second:    3433.87 [#/sec] (mean)
Time per request:       0.291 [ms] (mean)
Transfer rate:          2387.61 [Kbytes/sec] received

(顺便说一句,不要问我,为什么非 2xx 响应。他们通过网络是 200 OK。)

然后,再进行十倍的迭代:

评论:

Time taken for tests:   32.499 seconds
Requests per second:    3077.04 [#/sec] (mean)
Time per request:       0.325 [ms] (mean)
Transfer rate:          2139.51 [Kbytes/sec] received

没有评论:

Time taken for tests:   28.257 seconds
Requests per second:    3538.92 [#/sec] (mean)
Time per request:       0.283 [ms] (mean)
Transfer rate:          2460.66 [Kbytes/sec] received

呸,完美! 评论是邪恶的! ;)

好吧,我还做了几个,我只能向你展示这个没有评论的结果:

Time taken for tests:   37.399 seconds
Requests per second:    2673.84 [#/sec] (mean)
Time per request:       0.374 [ms] (mean)
Transfer rate:          1859.15 [Kbytes/sec] received

4。结果 - HTTP、Zend Opcache 已禁用:

好的,在意识到我打开了缓存之后,我从 PHP-FPM 配置中注释掉了扩展名(所以,确实,这就是这里运行的内容),重新启动服务,检查 phpinfo(),并收集新结果:

评论:

Time taken for tests:   34.756 seconds
Requests per second:    2877.23 [#/sec] (mean)
Time per request:       0.348 [ms] (mean)
Transfer rate:          2000.58 [Kbytes/sec] received

再一次:

Time taken for tests:   31.170 seconds
Requests per second:    3208.24 [#/sec] (mean)
Time per request:       0.312 [ms] (mean)
Transfer rate:          2230.73 [Kbytes/sec] received

没有评论:

Time taken for tests:   30.060 seconds
Requests per second:    3326.70 [#/sec] (mean)
Time per request:       0.301 [ms] (mean)
Transfer rate:          2313.10 [Kbytes/sec] received

再一次:

Time taken for tests:   32.990 seconds
Requests per second:    3031.23 [#/sec] (mean)
Time per request:       0.330 [ms] (mean)
Transfer rate:          2107.65 [Kbytes/sec] received

嗯。正如您所看到的,基本上:与 opcache 开/关状态没有什么差别!也不是在开/关之间(除了一个微小的提示,但已经看到了波动......)! :-o

5。结论

所以...最后,数字!好吧,事实上,无用的垃圾,但至少不仅仅是宗教猜测。出于混淆 data 的合理原因而感到困惑比缺少数据要好得多! :)

现在,在我确实在这方面浪费了足够多的时间之后,“cmets 成本多少”这个古老问题的答案仍然是一个谜。

由于中微子已经(令人难以置信地)被发现多年,我们可能会开始感到尴尬。有人最终会带来突破并最终检测到 PHP 评论的影响吗?没人知道...

【讨论】:

  • 令人难以置信的彻底答案。虽然 cmets 对性能的影响当然非常小,但它们对于解释器来说是一个可以跳过的步骤,并且看到 cmets 可以忽略的证明而不是假设是有用的。
  • 谢谢,这很有趣。 :) 虽然作为一个近似值很好,但我想说不要盲目相信结果,它们太模糊了。万一我碰巧长生不老,我可能会重复它a)更大的文件(我意识到为时已晚,它会更好地暴露差异),b)在更受控的环境中。
  • 您的结果变化太大。在你得出任何结论之前,你需要得到一个体面的标准偏差。现在没有人们期望的常规分布。当我有时间时,我可以尝试在资源有限的容器中运行它,以便它应该稳定。
【解决方案3】:

如果您想提高 PHP 应用程序的性能,那么您应该使用像 XCacheAPC 这样的字节码缓存。

这样服务器就不必在每个请求上解析 PHP 代码。当然,您的服务器必须支持这种扩展。

至于移除 cmets:我不确定这会产生巨大的影响(除了你的 cmets 很大)。

【讨论】:

    【解决方案4】:

    是的,它有影响!毫无疑问。

    每次 PHP 必须解释未以某种方式缓存的代码时,如果需要从磁盘读取更多数据,则 I/O 操作需要更长的时间。

    解释本身(如果没有以一种或另一种方式缓存)也需要更长的时间。

    性能损失很大程度上取决于使用的文件系统和缓存。在您的具体情况下,它可能并不那么重要。

    在我们编写的 Web 框架中,当我们打包分发文件用于生产环境时,我们会专门删除所有 cmets,以确保 LIVE 应用不会受到我们的惩罚许多 cmets(通常,我们的“String”例程的源文件在删除 cmets 之前占大约 169Kb,处理后仅占 46Kb)。

    我们已经放弃尝试衡量真正的惩罚,因为无法应对各种环境、文件系统和缓存机制。因此,我们决定以两种方式分发我们的代码:使用 cmets 和不使用 cmets。

    【讨论】:

    • 好点,但是您与接受答案的提交者犯了同样的谬误,后者主张相反的立场。没有数字,这只是……闲聊。
    【解决方案5】:

    它在 JavaScript 中有所不同,因为您希望向浏览器发送更少的数据,但在 php 中这无关紧要。 cmets 没有性能损失,因为编译器会忽略它们。 对于 Javascript,您可能希望拥有一份普通注释的 .js 文件的副本,但它们总是通过 minifier 运行它并创建 yourscript-min.js 用于生产。

    当您需要更改脚本时,只需更改您的正常脚本,然后重新创建缩小版本。仅在生产中使用缩小版。

    同样,对于 php 无关紧要,仅适用于 Javascript 和 html 文件。

    【讨论】:

      【解决方案6】:

      最好删除所有 js 文件 cmets 甚至使用压缩工具。减小 js 文件的大小会减少客户端的页面加载时间(因为那时他需要下载)并花费更少的带宽(当时谁买单)。

      【讨论】:

        【解决方案7】:

        如果您在系统上配置了一些东西来动态“压缩”您的 javascript,那么这样做有一些问题。实际上,我自己使用 .htaccess 实现了这一点,您可以获得巨大的性能提升,并在服务器本身上添加了注释代码。

        如果 PHP 中的 md5_file() 出现不同,我使用了 google 的关闭工具(服务器上的 jar 文件)并运行关闭。

        接下来,我使用 etags 为该文件分配一个标签。我还缓存了那个文件。

        当 etag 匹配时,我还返回一个未修改的 304。如果没有,那么我返回新文件并更新用户 etag。这很关键,因为如果您返回 200/OK,您将再次传回整个文件。

        这里的关键是如果你在运行中压缩你会失去性能,因为你总是在压缩和运行 PHP 代码。如果你花时间去做,你就可以正确地实现它。我个人喜欢这项技术,因为我可以在不发送非缩小版本的情况下修补实时服务器代码。这种技术的“第一次运行”的性能很慢,但随后的用户在服务器上拉下一个缓存文件,然后我返回 304 之后没有修改。您必须在压缩 PHP 文件中完成所有这些魔术。

        我在这里也提到了 .htaccess,因为我在那里使用了重写规则,并告诉网站哪些文件要压缩,哪些文件不压缩。例如mylibrary.jsc 告诉我的网站用闭包来压缩它。 yourlibrary.js 允许我有其他 .js 文件并按需压缩。

        【讨论】:

          【解决方案8】:

          您的 php 文件中可以包含 cmets,但我不建议在 Javascript 中使用大量 cmets。

          PHP 运行在服务器端,因此服务器可以使用 cmets 轻松处理 php 文件。

          【讨论】:

          • 荒谬。给我看一个基准,它显示 JS 中的 cmets 有任何明显的影响。它所做的只是增加下载文件的大小。它对执行时间没有影响。
          • 这就是我所说的,浏览器需要在执行之前加载JS文件。
          • 而且即使 if cmets 是一个巨大的性能消耗(它们不是,尝试一下),您可以通过使用缩小来修复它和文件大小。即使是最愚蠢的缩小器也可以去除 cmets 和不需要的空格(学生可以编写一个这样做的)。说“不要使用 cmets”比最可笑的微优化还要糟糕。
          • @VuralAcar,在您编辑之前,您说的是运行 JavaScript,而不是下载它。由于您已编辑,我将删除我的反对票。
          • @delnan 和 Brad,感谢您的更正和提示!我其实不想说“不要使用评论”,我只是想谈谈加载时间。很抱歉。
          【解决方案9】:

          很明显,这可以对巨大的流量产生影响,但在大多数设置中绝对可以忽略不计。考虑一个拥有 100 万用户的网站。并发连接和 Web 应用程序(例如,像 Joomla 这样的 CMS,它有许多 php 文件和大部分 cmets)对每个连接的请求都是那些带有大量注释和缩进的 php 文件。缩小应用程序的每个 php 文件会有所不同吗?我想如果您没有启用任何类型的缓存,它肯定会发生。这只是基本的 I/O 内容,文件越小,加载/处理它所需的内存就越少。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-07-24
            • 2011-02-09
            • 2010-10-02
            • 1970-01-01
            • 2011-06-09
            相关资源
            最近更新 更多