web-dev-qa-db-ja.com

コメントは解釈言語を遅くしますか?

私はPythonを使用しているのでこれを求めていますが、他のインタプリタ言語(Ruby、PHP、JavaScript)にも適用できます。

コードにコメントを残すたびにインタープリターの速度が低下しますか?インタプリタについての私の限られた理解によれば、それはプログラム式を文字列として読み込み、それらの文字列をコードに変換します。コメントを解析するたびに、それは無駄な時間のようです。

これは事実ですか?インタプリタ言語でのコメントに関する規約はありますか、それともその影響は無視できますか?

66
Mantas Vidutis

Pythonの場合、ソースファイルは実行前にコンパイルされます(.pycファイル)、およびコメントはプロセスで削除されます。ですからコメントcould億兆個ある場合はコンパイル時間を遅くしますが、実行時間には影響しません。

77
Luper Rouch

まあ、私は短い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秒かかりました。

したがって、答えはyesです。ループ内の4MBのコメントは、測定可能な違いをもたらします。

23
Rich Bradshaw

コメントは通常、解析ステージ内または解析ステージの前で取り除かれ、解析は非常に高速であるため、効果的に初期化時間が遅くなることはありません。

19
kennytm

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
5
Nick T

日常の使用では影響はほとんどありません。テストは簡単ですが、次のような単純なループを考えると、

For N = 1 To 100000: Next

お使いのコンピューターは、点滅(100,000カウントまで)を点滅よりも速く処理できます。特定の文字で始まるテキスト行を無視すると、10,000倍以上速くなります。

心配しないでください。

4
NibblyPig

インタプリタの実装方法によって異なります。最も合理的に最新のインタープリターは、実際の実行の前にソースコードに対して少なくとも少し前処理を行います。これには、コメントを削除して、それ以降は何の違いもないようにすることが含まれます。

かつては、メモリが厳しく制限されていたとき(たとえば、アドレス可能な合計メモリが64Kであり、ストレージ用のカセットテープなど)、そのようなことを当然のこととすることはできませんでした。 Apple II、Commodore PET、TRS-80など)の時代には、プログラマがコメント(さらには空白文字)を明示的に削除して実行速度を向上させることはかなり日常的でした。これはまた、当時日常的に使用されていた多くのソースコードレベルのハッキングの1つにすぎませんでした。1

もちろん、これらのマシンには、一度に1つの命令しか実行できないCPUがあり、クロック速度は約1 MHzで、8ビットのプロセッサレジスタしかなかったということにも役立ちました。ゴミ箱でしか見つけられない機械でさえ、それよりもはるかに高速であり、面白くさえありません...


1.別の例として、Applesoftでは、行に番号を付ける方法に応じて、速度が多少向上または低下する可能性があります。メモリが機能する場合、速度の向上はgotoステートメントのターゲットが16の倍数であったときです。

4
Jerry Coffin

スクリプトを実行可能な形式に解析するため、コメントがあると起動時間が遅くなります。ただし、ほとんどの場合、コメントによってランタイムが遅くなることはありません。

さらに、Pythonでは、.pyファイルを.pycにコンパイルできます。コメントには含まれません(希望するはずです)。これは、スクリプトが既にコンパイルされている場合でも、起動ヒットが発生しないことを意味します。

1
MarkR

インタープリターについての私の限られた理解は、プログラム式をストリングとして読み取り、それらのストリングをコードに変換することです。

ほとんどのインタープリターはテキスト(コード)を読み取り、抽象構文ツリーデータ構造を生成します。
その構造には、テキスト形式のコードが含まれておらず、もちろんコメントも含まれていません。プログラムを実行するには、そのツリーだけで十分です。しかし、インタプリタは、効率上の理由から、さらに一歩進んでバイトコードを生成します。そしてPythonはまさにそれを行います。

コードとコメントは、あなたが書いた形式では、単に存在しないと言えます。
プログラムが実行されているとき。したがって、コメントは実行時にプログラムを遅くしません。

(*)テキスト以外のコードを表すために他の内部構造を使用しないインタープリター、
つまり構文ツリーは、あなたが述べたとおりに実行する必要があります。実行時にコードを何度も解釈します。

1

コメントの使い方が重要なのかな。たとえば、三重引用符はドキュメント文字列です。それらを使用すると、コンテンツが検証されます。ライブラリを自分のPython 3コードにインポートしていたときに問題が発生しました...\Nの構文に関してこのエラーが発生しました。行番号を調べたところ、内容がわかりました三重引用符のコメントの中で、私は多少驚いたが、Pythonの新機能として、ブロックコメントが構文エラーで解釈されるとは思っていなかった。

単にあなたがタイプすると:

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

Python 2はエラーをスローしませんが、Python 3レポート:SyntaxError:(unicode error) 'unicodeescape' codec ca n't be bytes in position 14-15:malformed\N character escape

したがって、Python 3は、明らかに三重引用符を解釈し、有効な構文であることを確認しています。

ただし、1行のコメントに変更した場合:#(つまり、\ Device\NPF_ ..)
エラーは発生しません。

パフォーマンスの変化が見られる場合は、三重引用符のコメントを1行に置き換えたのでしょうか。

0
continuousqa

他の回答がすでに述べているように、Python=のような現代の解釈言語は、最初にソースを解析してコンパイルしてバイトコードに変換し、パーサーはコメントを単に無視します。これは明らかに、速度の低下はソースが実際に解析される起動時に発生します。

パーサーはコメントを無視するため、コンパイルフェーズは基本的に、入力したコメントの影響を受けません。ただし、コメント自体のバイトは実際に読み込まれ、解析中にスキップされます。つまり、非常に多くのコメント(たとえば、数百メガバイト)がある場合、インタープリターの速度が低下します。しかし、これもまた、コンパイラを遅くします。

0
MAK

この質問は本当に古いですが、実行時間に影響を与えないという間違った受け入れられた回答を読んだ後、実際に実行時間に影響する量を確認できる簡単な例を紹介します。
constants.py_というファイルがあります。リストには、チェスのさまざまなアクションがすべて含まれています。

_LABELS = [ "a1b1"
    "a1c1", 
    "a1d1", 
    "a1e1", 
    "a1f1",....]
_

リストLABELSには2272要素が含まれています。別のファイルで私は呼び出す:

_import constants
np.array(constants.LABELS)
_

私はそれを10回測定し、コードの実行には約0.597ミリ秒かかりました。次に、ファイルを変更し、各要素の横に(2272回)コメントを挿入しました。

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

np.array(constants.LABELS)の実行時間を10回測定した後、平均実行時間は4.28ミリ秒になり、約7倍遅くなります。
そのため、はい、コメントがたくさんある場合、実行時間に影響します。

0
Code Pope