【问题标题】:Do comments affect Perl performance?注释会影响 Perl 的性能吗?
【发布时间】:2010-09-21 04:00:22
【问题描述】:

我正在优化一些经常运行的 Perl 代码(每个文件每天一次)。

cmets 会减慢 Perl 脚本的速度吗?我的实验倾向于否:

use Benchmark;
timethese(20000000, {
    'comments' => '$b=1;
# comment  ... (100 times)
', 'nocomments' => '$b=1;'});

给出几乎相同的值(除了噪声)。

Benchmark: timing 10000000 iterations of comments, nocomments...
  comments:  1 wallclock secs ( 0.53 usr +  0.00 sys =  0.53 CPU) @ 18832391.71/s (n=10000000)
nocomments:  0 wallclock secs ( 0.44 usr +  0.00 sys =  0.44 CPU) @ 22935779.82/s (n=10000000)

Benchmark: timing 20000000 iterations of comments, nocomments...
  comments:  0 wallclock secs ( 0.86 usr + -0.01 sys =  0.84 CPU) @ 23696682.46/s (n=20000000)
nocomments:  1 wallclock secs ( 0.90 usr +  0.00 sys =  0.90 CPU) @ 22099447.51/s (n=20000000)

如果我将 cmets 和非 cmets 版本作为单独的 Perl 脚本运行,我会得到类似的结果。

这似乎违反直觉,如果没有别的,解释器每次都需要将 cmets 读入内存。

【问题讨论】:

  • perl 不做某种即时编译吗?也许 cmets 会提前被丢弃?
  • 也许你没有添加足够多的 cmets 来产生影响。
  • 我打赌换行也会减慢 perl 的速度。你应该像真正的 perl 大师那样做,把你所有的代码放在一行。
  • 我假设 davr 是在开玩笑,但由于代码是从 CVS 构建的,我只是考虑在构建过程中运行一个简单的正则表达式。主代码仍然是可读的。

标签: performance perl comments


【解决方案1】:

运行时性能?没有。

解析和词法分析性能?是的,当然。

由于 Perl 倾向于动态解析和 lex,因此 cmets 会影响“启动”性能。

它们会显着影响它吗?不太可能。

【讨论】:

    【解决方案2】:

    Perl 是一种即时编译语言,因此 cmets 和 POD 对运行时性能没有影响。

    注释和 POD 对编译时间的影响微乎其微,但它们对 Perl 来说非常容易和快速解析,几乎不可能衡量性能影响。您可以通过使用 -c 标志来亲自查看。

    在我的 Macbook 上,一个包含 2 条语句和 1000 行 70 个字符 cmets 的 Perl 程序与一个只有 2 个打印语句的 1000 行空 cmets 的编译时间相同。请务必运行每个基准测试两次,以允许您的操作系统缓存文件,否则您的基准测试是从磁盘读取文件的时间。

    如果启动时间对您来说是个问题,那不是因为 cmets 和 POD。

    【讨论】:

      【解决方案3】:

      Perl 编译一个脚本然后执行它。注释略微减慢编译阶段,但对运行阶段的影响为零。

      【讨论】:

        【解决方案4】:

        Perl 不像 shell 脚本那样是一种脚本语言。解释器不会逐行读取文件。 Perl 程序的执行分为两个基本阶段:编译和运行时 [1]。在编译阶段,源代码被解析并转换为字节码。在运行阶段,字节码在虚拟机上执行。

        注释会减慢解析阶段的速度,但与解析脚本本身所需的时间(对于大多数程序来说已经非常小)相比,差异可以忽略不计。您真正关心解析时间的唯一一次是在网络服务器环境中,该程序每秒可以调用多次。 mod_perl 的存在就是为了解决这个问题。

        您正在使用Benchmark。那挺好的!你应该寻找改进算法的方法——而不是微优化。 Devel::DProf 可能有助于找到任何热点。您绝对不应该在错误的尝试中剥离 cmets 以使您的程序更快。你只会让它无法维护。


        [1] 这通常称为“及时”编译。 Perl 实际上还有几个阶段,例如 INITEND,在这里无关紧要。

        【讨论】:

        • Devel::DProf 是旧的损坏,只有子程序级别的分析。 Devel::NYTProf 是具有更细粒度的新热点..
        【解决方案5】:

        重点是:优化瓶颈。读入一个文件包括:

        • 打开文件,
        • 读取其内容,
        • 关闭文件,
        • 解析内容。

        在这些步骤中,读取是迄今为止最快的部分(我不确定是否要关闭,它是一个系统调用,但您不必等待它完成)。即使它是整个事情的 10%(我认为不是),然后将其减少一半只会提高 5% 的性能,代价是缺少 cmets(这是一件非常糟糕的事情)。对于解析器,丢弃以 # 开头的行并不是明显的减速。在那之后,cmets 消失了,所以不会有减速。

        现在,想象一下,通过剥离所有 cmets,您实际上可以将“阅读脚本”部分提高 5%(这是一个非常乐观的估计,见上文)。 “看剧本”占剧本总耗时的比例有多大?当然,这取决于它做了多少,但是由于 perl 脚本通常会读取至少一个文件,因此最多为 50%,但是由于 perl 脚本通常会做更多的事情,因此诚实的估计会将其降低到某个范围内1%。因此,通过剥离所有 cmets 的预期效率提升是at most(非常乐观)2.5%,但实际上更接近 0.05%。然后,实际上提供超过 1% 的那些已经很快,因为它们几乎什么都不做,所以你又在错误的点上进行优化。

        总结,优化瓶颈。

        【讨论】:

        • 如果我要添加一个条目,我会指出行尾 cmets 是迄今为止最容易丢弃的。 Perldoc 可能是下一个最简单的:整行,不能嵌套(当你说 =cut 时,它就完成了。),确定的行块......
        • 实际上,读取文件从找到文件开始。如果 Perl 必须搜索很长的 @INC,那可能很重要。例如,参见perl.com/lpt/a/2005/12/21/a_timely_start.html
        • 是的,但在这里我假设直接调用包括路径。如果某些 cron 作业没有指定脚本的位置,那么这实际上是一个值得优化的瓶颈。
        【解决方案6】:

        Benchmark 模块在这种情况下是无用的。它只是测量一遍又一遍地运行代码的时间。由于您的代码实际上并没有做任何事情,因此大部分代码都对其进行了优化。这就是为什么您会看到它每秒运行 2200 万次。

        我在Mastering Perl 中几乎有整整一章的内容。基准技术的测量误差约为 7%。您的基准数字正好在这个范围内,因此几乎没有区别。

        【讨论】:

          【解决方案7】:

          来自保罗·汤布林斯的评论:

          perl 不做某种即时编译吗?也许 cmets 会提前被丢弃? ——

          是的,Perl 可以。

          它是一种介于编译型和解释型之间的编程语言。代码被即时编译然后运行。 cmets通常没有任何区别。它可能会产生的最大影响是,当它最初逐行解析文件并预编译它时,您可能会看到纳秒级的差异。

          【讨论】:

            【解决方案8】:

            我希望一条评论只会被解析一次,而不是在循环中多次解析,所以我怀疑这是一个有效的测试。

            我希望 cmets 会稍微减慢编译速度,但我希望删除它们太小了。

            【讨论】:

              【解决方案9】:

              Perl cmets 会减慢脚本的速度吗?好吧,解析它,是的。解析后执行?不。脚本多久被解析一次?只有一次,所以如果你在 for 循环中有注释,注释会被解析丢弃一次,在脚本甚至运行之前,一旦它开始运行,注释就已经消失了(并且脚本不会在内部存储为脚本Perl),因此无论 for 循环重复多少次,注释都不会产生影响。解析器可以多快跳过 cmets? Perl cmets 的完成方式非常快,因此我怀疑您会注意到。如果您有 5 行代码,并且每行之间有 1 个 Mio 行 cmets,您会注意到启动时间更长……但是这种可能性有多大,那么大的注释有什么用?

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2011-11-11
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2021-04-29
                • 2012-02-04
                • 2011-01-28
                • 1970-01-01
                相关资源
                最近更新 更多