评论会减慢解释语言的速度吗?

时间:2010-04-28 15:46:41

标签: python comments interpreter interpreted-language

我问这个是因为我使用Python,但它也适用于其他解释语言(Ruby,PHP,JavaScript)。

每当我在代码中留下评论时,我是否会放慢口译员的速度?根据我对解释器的有限理解,它以字符串形式读取程序表达式,然后将这些字符串转换为代码。似乎每次解析评论时都会浪费时间。

是这样的吗?在解释语言中是否有一些评论惯例,或者效果可以忽略不计?

11 个答案:

答案 0 :(得分:75)

对于Python的情况,源文件在执行之前被编译(.pyc文件),并且在此过程中将删除注释。所以注释可以减慢编译时间,如果你有它们的gazillions,但它们不会影响执行时间。

答案 1 :(得分:23)

好吧,我写了这样一个简短的python程序:

for i in range (1,1000000):
    a = i*10

这个想法是,做一个简单的计算次数。

通过计时,运行需要0.35±0.01秒。

然后我用这样插入的整个King James Bible重写了它:

for i in range (1,1000000):
    """
The Old Testament of the King James Version of the Bible

The First Book of Moses:  Called Genesis


1:1 In the beginning God created the heaven and the earth.

1:2 And the earth was without form, and void; and darkness was upon
the face of the deep. And the Spirit of God moved upon the face of the
waters.

1:3 And God said, Let there be light: and there was light.

...
...
...
...

Even so, come, Lord Jesus.

22:21 The grace of our Lord Jesus Christ be with you all. Amen.
    """
    a = i*10

这次运行需要0.4±0.05秒。

所以答案是。循环中的4MB注释会产生可测量的差异。

答案 2 :(得分:19)

注释通常在解析阶段或之前被删除,并且解析速度非常快,因此有效注释不会减慢初始化时间。

答案 3 :(得分:5)

像Rich这样的剧本做了一些评论(只有大约500kb的文字):

# -*- coding: iso-8859-15 -*-
import timeit

no_comments = """
a = 30
b = 40
for i in range(10):
    c = a**i * b**i
"""
yes_comment = """
a = 30
b = 40

# full HTML from http://en.wikipedia.org/
# wiki/Line_of_succession_to_the_British_throne

for i in range(10):
    c = a**i * b**i
"""
loopcomment = """
a = 30
b = 40

for i in range(10):
    # full HTML from http://en.wikipedia.org/
    # wiki/Line_of_succession_to_the_British_throne

    c = a**i * b**i
"""

t_n = timeit.Timer(stmt=no_comments)
t_y = timeit.Timer(stmt=yes_comment)
t_l = timeit.Timer(stmt=loopcomment)

print "Uncommented block takes %.2f usec/pass" % (
    1e6 * t_n.timeit(number=100000)/1e5)
print "Commented block takes %.2f usec/pass" % (
    1e6 * t_y.timeit(number=100000)/1e5)
print "Commented block (in loop) takes %.2f usec/pass" % (
    1e6 * t_l.timeit(number=100000)/1e5)


C:\Scripts>timecomment.py
Uncommented block takes 15.44 usec/pass
Commented block takes 15.38 usec/pass
Commented block (in loop) takes 15.57 usec/pass

C:\Scripts>timecomment.py
Uncommented block takes 15.10 usec/pass
Commented block takes 14.99 usec/pass
Commented block (in loop) takes 14.95 usec/pass

C:\Scripts>timecomment.py
Uncommented block takes 15.52 usec/pass
Commented block takes 15.42 usec/pass
Commented block (in loop) takes 15.45 usec/pass

根据David的评论进行编辑:

 -*- coding: iso-8859-15 -*-
import timeit

init = "a = 30\nb = 40\n"
for_ = "for i in range(10):"
loop = "%sc = a**%s * b**%s"
historylesson = """
# <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
# blah blah...
# --></body></html> 
"""
tabhistorylesson = """
    # <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    # blah blah...
    # --></body></html> 
"""

s_looped = init + "\n" + for_ + "\n" + tabhistorylesson + loop % ('   ','i','i')
s_unroll = init + "\n"
for i in range(10):
    s_unroll += historylesson + "\n" + loop % ('',i,i) + "\n"
t_looped = timeit.Timer(stmt=s_looped)
t_unroll = timeit.Timer(stmt=s_unroll)

print "Looped length: %i, unrolled: %i." % (len(s_looped), len(s_unroll))

print "For block takes %.2f usec/pass" % (
    1e6 * t_looped.timeit(number=100000)/1e5)
print "Unrolled it takes %.2f usec/pass" % (
    1e6 * t_unroll.timeit(number=100000)/1e5)


C:\Scripts>timecomment_unroll.py
Looped length: 623604, unrolled: 5881926.
For block takes 15.12 usec/pass
Unrolled it takes 14.21 usec/pass

C:\Scripts>timecomment_unroll.py
Looped length: 623604, unrolled: 5881926.
For block takes 15.43 usec/pass
Unrolled it takes 14.63 usec/pass

C:\Scripts>timecomment_unroll.py
Looped length: 623604, unrolled: 5881926.
For block takes 15.10 usec/pass
Unrolled it takes 14.22 usec/pass

答案 4 :(得分:4)

这种影响对于日常使用来说是可以忽略的。它很容易测试,但是如果你考虑一个简单的循环,例如:

For N = 1 To 100000: Next

您的计算机可以比闪烁更快地处理(计数到100,000)。忽略以某个字符开头的文本行将快10,000倍。

不要担心。

答案 5 :(得分:4)

这取决于解释器的实现方式。最合理的现代解释器在任何实际执行之前至少对源代码进行一些预处理,这将包括删除注释,以便它们从那一点开始没有区别。

有一段时间,当内存受到严重限制时(例如,64K总可寻址内存,以及用于存储的盒式磁带),您无法将此类内容视为理所当然。回到Apple II,Commodore PET,TRS-80等的那一天,程序员明确删除注释(甚至是空白空间)以提高执行速度是相当常规的。这也只是 1 时常规使用的许多源代码级别的黑客攻击之一。

当然,这也有助于这些机器的CPU只能一次执行一条指令,时钟速度约为1 MHz,并且只有8位处理器寄存器。即使是现在只能在垃圾箱中找到的机器也比那些它甚至不好笑的机器快得多......


1.另一个例子,在Applesoft中,你可以获得或失去一点速度,具体取决于你的编号方式。如果内存服务,则速度增益是当goto语句的目标是16的倍数时。 功能

答案 6 :(得分:1)

发表评论会减慢启动时间,因为脚本将被解析为可执行的形式。但是,在大多数情况下,注释不会减慢运行时间。

此外在python中,您可以将.py文件编译为.pyc,它不包含注释(我希望) - 这意味着如果脚本已经编译,您将不会获得启动命中。

答案 7 :(得分:1)

  

我对一个人的理解有限   解释器是它读取程序   表达式作为字符串和转换   那些字符串代码。

大多数口译员阅读文本(代码)并生成抽象语法树数据结构 该结构不包含文本形式的代码,当然也没有注释。只有那棵树足以执行程序。但是出于效率原因,解释器更进一步并产生字节代码。而Python正是这样做的。

我们可以说,您编写的表单中的代码和注释只是不存在
当程序运行时。所以不,评论不会在运行时减慢程序的速度。

(*)不使用其他内部结构来表示除文本以外的代码的解释器,
即一个语法树,必须完全按照你提到的做。在运行时一次又一次地解释代码。

答案 8 :(得分:0)

正如其他答案已经说明的那样,像Python这样的现代解释语言首先将源解析并编译为字节码,而解析器只是忽略了注释。这显然意味着任何速度损失只会在启动时实际解析源。

因为解析器忽略了注释,所以编译阶段基本上不受您放入的任何注释的影响。但是注释本身中的字节实际上是被读入的,然后在解析期间被跳过。这意味着,如果您有大量的评论(例如数百兆字节),这会降低解释器的速度。但是,这也会减慢任何编译器的速度。

答案 9 :(得分:0)

我想知道如何使用评论。例如,三引号是文档字符串。如果您使用它们,则会验证内容。我在一段时间内遇到了一个问题,我将一个库导入我的Python 3代码......我在\ N上的语法上遇到了这个错误。我查看了行号,它是三重引用评论中的内容。我有点惊讶。 Python新手,我从未想过会因语法错误而解释块注释。

只需键入:

'''
(i.e. \Device\NPF_..)
'''

Python 2不会抛出错误,但Python 3报告: SyntaxError :( unicode error)'unicodeescape'编解码器无法解码位置14-15中的字节:格式错误\ N字符转义

因此,Python 3显然正在解释三重引用,确保它是有效的语法。

但是,如果变成单行注释:#(即\ Device \ NPF_ ..)
没有错误结果。

我想知道如果会看到性能变化,三重引用评论是否会被单行代替。

答案 10 :(得分:0)

这个问题确实很老,但是在阅读了公认的答案之后,该答案声称这不会影响执行时间,这是错误的,我给您一个简单的示例,您可以在其中查看并检查它影响执行的数量。确实是时间。
我有一个名为constants.py的文件。它在列表中包含国际象棋的所有不同动作:

LABELS = [ "a1b1"
    "a1c1", 
    "a1d1", 
    "a1e1", 
    "a1f1",....]

列表LABELS包含2272个元素。在另一个文件中,我称:

import constants
np.array(constants.LABELS)

我对其进行了十次测量,代码执行大约需要0.597毫秒。 现在,我更改了文件,并在每个元素旁边插入了2272次注释:

LABELS = [ "a1b1",  # 0 
            "a1c1", # 1
            "a1d1", # 2
            "a1e1", # 3
            "a1f1", # 4
             ...,
            "Q@h8", # 2271]

现在,在测试np.array(constants.LABELS)十次之后,我的平均执行时间为4.28毫秒,因此慢了约7倍。
因此,是的,如果您有很多注释,它将影响执行时间。