我之所以这样问是因为我使用Python,但是它也可以应用于其他解释语言(Ruby,PHP,JavaScript)。
每当我在代码中留下评论时,我是否会放慢解释器的速度?根据我对解释器的有限了解,它以字符串形式读取程序表达式,然后将这些字符串转换为代码。似乎每次解析评论时都是浪费时间。
是这样吗 是否有一些解释性语言的注释约定,或者其影响可以忽略不计?
我之所以这样问是因为我使用Python,但是它也可以应用于其他解释语言(Ruby,PHP,JavaScript)。
每当我在代码中留下评论时,我是否会放慢解释器的速度?根据我对解释器的有限了解,它以字符串形式读取程序表达式,然后将这些字符串转换为代码。似乎每次解析评论时都是浪费时间。
是这样吗 是否有一些解释性语言的注释约定,或者其影响可以忽略不计?
Answers:
对于Python而言,源文件(.pyc
文件)在执行之前先进行编译,然后在过程中删除注释。因此,如果您有大量注释,则注释可能会减慢编译时间,但它们不会影响执行时间。
gazillion
在这种情况下使用
好吧,我写了一个简短的python程序,像这样:
for i in range (1,1000000):
a = i*10
想法是,做一个简单的时间计算负载。
通过计时,运行时间为0.35±0.01秒。
然后,我将整个《英王钦定版圣经》插入如下:
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的评论可衡量。
用一些注释(仅约500kb的文本)编写了类似Rich的脚本:
# -*- 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
这取决于解释器的实现方式。最合理的现代解释器在任何实际执行之前都会对源代码进行至少一些预处理,这将包括删除注释,因此从那时起它们没有任何区别。
一次,当内存受到严重限制时(例如64K总可寻址内存,以及用于存储的盒式磁带),您将无法接受这样的事情。早在Apple II,Commodore PET,TRS-80等时代,对于程序员来说,显式删除注释(甚至是空格)以提高执行速度是相当常规的。这也是当时1经常使用的许多源代码级黑客之一。
当然,这也有助于使这些机器的CPU一次只能执行一条指令,时钟速度约为1 MHz,并且只有8位处理器寄存器。甚至您现在只能在垃圾箱中找到的机器也比那些机器快得多,甚至还不有趣...
1.再举一个例子,在Applesoft中,您可能会因行编号方式的不同而有所不同。如果有内存,则速度增加是当goto语句的目标是16的倍数时。
注释会减慢启动时间,因为脚本将被解析成可执行文件。但是,在大多数情况下,注释不会减慢运行时间。
此外,在python中,您可以将.py文件编译成.pyc,其中将不包含注释(我希望如此)-这意味着,即使脚本已经编译,也不会受到启动的影响。
s/will slow down the startup time/will slow down the startup time immeasurably
。s/in most cases comments don't slow down runtime/in all cases comments don't slow down runtime
我对解释器的有限理解是,它以字符串形式读取程序表达式并将这些字符串转换为代码。
大多数解释器读取文本(代码)并生成抽象语法树数据结构。
该结构不包含文本形式的代码,当然也不包含任何注释。仅那棵树就足以执行程序。但是由于效率的原因,解释器会更进一步,并产生字节码。Python正是这样做的。
我们可以说,代码和注释,在你写了他们的形式,仅仅是不存在的,
在程序运行时。因此,不,注释不会在运行时降低程序速度。
(*)不使用其他内部结构来表示除文本(
即语法树)以外的代码的解释器,必须完全按照您提到的做。在运行时一次又一次地解释代码。
正如其他答案已经指出的那样,像Python这样的现代解释语言首先会解析源并将其编译为字节码,而解析器只会忽略注释。显然,这意味着只有在实际解析源时,才会在启动时发生速度损失。
因为解析器会忽略注释,所以编译阶段基本上不受您放入的任何注释的影响。但是注释本身中的字节实际上是被读入的,然后在解析过程中被跳过。这意味着,如果您有大量的注释(例如数百兆字节),这会使解释器变慢。但这又会减慢任何编译器的速度。
我想知道评论的使用方式是否重要。例如,三引号是一个文档字符串。如果使用它们,内容将被验证。不久前,我在将库导入到我的Python 3代码中时遇到了一个问题...关于\ N语法的错误。我查看了行号,它是三引号注释中的内容。我有些惊讶。我是Python的新手,我从没想过会因为语法错误而解释块注释。
只需输入以下内容即可:
'''
(i.e. \Device\NPF_..)
'''
Python 2不会引发错误,但是Python 3会报告:SyntaxError:(unicode错误)“ unicodeescape”编解码器无法解码位置14-15的字节:格式错误的\ N字符转义
因此,Python 3显然在解释三引号,以确保它是有效的语法。
但是,如果变成一行注释:#(即\ Device \ NPF_ ..)
没有错误结果。
我想知道是否会看到性能变化,是否用单行替换了三引号注释。
这个问题确实很老,但是在阅读了公认的答案后,即它不会影响执行时间(这是错误的)之后,我给您提供一个简单的示例,您可以在其中查看并检查它确实影响执行时间的数量。
我有一个名为的文件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毫秒,因此慢了大约七倍。
因此,是的,如果您有很多注释,它将影响执行时间。
np.array(constant.LABELS)
十次并测量该语句的平均执行时间。我将在文本中对此进行澄清。