Verlangsamen Kommentare eine interpretierte Sprache?

70

Ich frage dies, weil ich Python verwende, aber es könnte auch für andere interpretierte Sprachen gelten (Ruby, PHP, JavaScript).

Verlangsame ich den Interpreter, wenn ich einen Kommentar in meinem Code hinterlasse? Nach meinem begrenzten Verständnis eines Interpreters liest er Programmausdrücke als Zeichenfolgen ein und konvertiert diese Zeichenfolgen dann in Code. Es scheint, dass jedes Mal, wenn ein Kommentar analysiert wird, dies Zeitverschwendung ist.

Ist das der Fall? Gibt es eine Konvention für Kommentare in interpretierten Sprachen oder ist der Effekt vernachlässigbar?

Mantas Vidutis
quelle
3
Dies war sicherlich ein Problem in BASIC auf meinem alten Commodore 64. Sprachen und Hardware haben sich seitdem dramatisch verbessert.
Fred Larson
6
Sie sollten sich bewusst sein, dass der Begriff "interpretiert" nicht viel bedeutet. Python wird per Bytecode kompiliert und nicht direkt aus dem Quellcode interpretiert.
Thomas Wouters
Es könnte interessant sein, JavaScript in Bezug auf diese Frage in Betracht zu ziehen. Ich glaube, JQuery hat zum Beispiel eine Version, die keine Kommentare und keine zusätzlichen Leerzeichen enthält, um die Übertragungszeit zu minimieren.
Fred Larson
15
Das Entfernen von Kommentaren und Leerzeichen (und das Zusammenführen von Dingen so weit wie möglich) ist in JavaScript ziemlich häufig, aber nicht wirklich, um das Parsen oder die Ausführung zu beschleunigen. Es dreht sich alles um Netzwerkübertragungszeit (und Bandbreite für ausgelastete Standorte).
Thomas Wouters
4
Beispiel: Die Quelle für google.com/index.html ist praktisch verschleiert, da Google jede JS-Variable auf maximal 3 Buchstaben zerquetscht und jedes mögliche Leerzeichen entfernt hat.
Nick T

Antworten:

89

Im Fall von Python werden Quelldateien vor der Ausführung kompiliert (die .pycDateien) und die Kommentare werden dabei entfernt. Kommentare können also die Kompilierungszeit verlangsamen, wenn Sie Millionen davon haben, aber sie haben keinen Einfluss auf die Ausführungszeit.

Luper Rouch
quelle
36
+1, weil mir die gazillionVerwendung in diesem Zusammenhang sehr gut gefallen hat
M. Williams
2
Es ist schwer vorstellbar, wie hoch das Verhältnis von Kommentar zu Code sein müsste, bevor dies erkennbar wäre.
Mike Graham
3
@ Mike: möglicherweise 1 Gazillion: 1?
Seth Johnson
1
Ich bin mir bei mehreren Millionen nicht ganz sicher, aber ich denke, Sie denken richtig.
M. Williams
Ich stelle nur fest, dass selbst die Kompilierungszeit nur einmal vorkommt und dann zwischengespeichert wird.
Ian Bicking
27

Nun, ich habe ein kurzes Python-Programm wie dieses geschrieben:

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

Die Idee ist, eine einfache Berechnung viele Male durchzuführen.

Zu diesem Zeitpunkt dauerte der Lauf 0,35 ± 0,01 Sekunden.

Ich habe es dann mit der gesamten King James Bibel umgeschrieben, die so eingefügt wurde:

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

Diesmal dauerte der Lauf 0,4 ± 0,05 Sekunden.

Die Antwort lautet also ja . 4 MB Kommentare in einer Schleife machen einen messbaren Unterschied.

Rich Bradshaw
quelle
18
+1 für ein wissenschaftliches Experiment und die Heilige Bibel im selben Beitrag. 8vD
Fred Larson
44
Das ist kein Kommentar. Es ist ein String-Literal. Wenn Sie sich außerdem den tatsächlichen Bytecode für Ihre beiden Codeblöcke ansehen, werden Sie keinen Unterschied feststellen . Die Zeichenfolge wird einmal analysiert und ist überhaupt nicht an den Berechnungen beteiligt. Sie sollten dieselbe Verlangsamung sehen, wenn Sie die Zeichenfolge außerhalb der Schleife platzieren.
Thomas Wouters
14
+1, um einer dummen Abwertung entgegenzuwirken, und Requisiten, um trotz des fehlerhaften Ansatzes tatsächlich zu experimentieren. TIAS (Try it and see) bietet oft bessere Antworten als abstrakte Diskussionen.
3Dave
6
@ David, der Fall, in dem dieser Test durchgeführt wird, ist weder der von OP beschriebene noch repräsentativ für irgendetwas wie Code, den Leute tatsächlich schreiben.
Mike Graham
3
@Rich, kannst du den String in einen Kommentar konvertieren und das neue Timing posten?
smci
19

Kommentare werden normalerweise in oder vor der Analysephase entfernt, und die Analyse ist sehr schnell, sodass Kommentare die Initialisierungszeit nicht verlangsamen.

kennytm
quelle
10
Kommentare müssen entfernt werden, damit sie bei ausreichend großen Kommentaren das Programm verlangsamen. Aber Sie müssen enorme Kommentare (MBs? GBs?) Haben, bevor Sie es überhaupt messen können.
Henrik Hansen
3
Megabyte an Kommentaren bedeuten, dass mehr als Megabyte Code vorhanden sind. Die Zeit für das eigentliche Parsen und Kompilieren würde die "kleine" Zeit zum Entfernen von Kommentaren überfordern.
Kennytm
11
Ich ging voran und probierte es aus. Auf meinem speziellen Testsystem dauert das Parsen und Ausführen von ungefähr 10 Megas Python-Kommentaren (und einer Zuweisungsanweisung) 349 ms. Das Verhältnis von Quellbytes zu Zeit scheint in diesem Fall mit etwa 28.000 Bytes pro ms ziemlich konstant zu sein. Das gleiche Skript auf Codepad ist (wie ich es mir vorgestellt habe) langsamer: codepad.org/Ckevfqmq
AKX
Ich bin sicher, man kann ein pathologisches Beispiel für das Gegenteil konstruieren. Oh schau, sieh dir die Antwort von Rich Bradshaw an. Für alle praktischen Zwecke haben Sie natürlich völlig Recht.
Janneb
5

Der Effekt ist für den täglichen Gebrauch vernachlässigbar. Es ist leicht zu testen, aber wenn Sie eine einfache Schleife in Betracht ziehen, wie zum Beispiel:

For N = 1 To 100000: Next

Ihr Computer kann dies (bis 100.000) schneller verarbeiten, als Sie blinken können. Das Ignorieren einer Textzeile, die mit einem bestimmten Zeichen beginnt, ist mehr als 10.000 Mal schneller.

Mach dir keine Sorgen.

NibblyPig
quelle
5

Habe ein Skript wie das von Rich mit einigen Kommentaren erstellt (nur etwa 500 KB Text):

# -*- 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

Bearbeiten Sie gemäß Davids Kommentar:

 -*- 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
Nick T.
quelle
@Nick, ich würde erwarten, dass jeder nicht naive Interpreter nur die Kommentare für den ersten Durchgang durch die Schleife analysiert. Haben Sie dies entweder mit einer abgewickelten Schleife oder durch Einfügen von ein paar hundert Kommentarzeilen in den Code versucht?
3Dave
4

Dies hängt davon ab, wie der Interpreter implementiert ist. Die meisten einigermaßen modernen Interpreten führen vor jeder tatsächlichen Ausführung zumindest eine gewisse Vorverarbeitung des Quellcodes durch. Dazu gehört auch das Entfernen der Kommentare, damit sie ab diesem Zeitpunkt keinen Unterschied mehr machen.

Zu einer Zeit, als der Speicher stark eingeschränkt war (z. B. 64 KB adressierbarer Gesamtspeicher und Kassetten zur Speicherung), konnte man solche Dinge nicht als selbstverständlich betrachten. Zu Zeiten von Apple II, Commodore PET, TRS-80 usw. war es für Programmierer ziemlich routinemäßig, Kommentare (und sogar Leerzeichen) explizit zu entfernen, um die Ausführungsgeschwindigkeit zu verbessern. Dies war auch nur einer von vielen Hacks auf Quellcode-Ebene, die zum Zeitpunkt 1 routinemäßig eingesetzt wurden .

Natürlich hat es auch geholfen, dass diese Maschinen CPUs hatten, die jeweils nur einen Befehl ausführen konnten, Taktraten um 1 MHz hatten und nur 8-Bit-Prozessorregister hatten. Sogar eine Maschine, die Sie jetzt nur in einem Müllcontainer finden würden, ist so viel schneller als diese, dass es nicht einmal lustig ist ...


1. In einem anderen Beispiel können Sie in Applesoft ein wenig an Geschwindigkeit gewinnen oder verlieren, je nachdem, wie Sie die Zeilen nummeriert haben. Wenn Speicher dient, war der Geschwindigkeitsgewinn, wenn das Ziel einer goto-Anweisung ein Vielfaches von 16 war.

Jerry Sarg
quelle
1

Kommentare verlangsamen die Startzeit, da die Skripte in eine ausführbare Form analysiert werden. In den meisten Fällen verlangsamen Kommentare jedoch nicht die Laufzeit.

Zusätzlich können Sie in Python die .py-Dateien in .pyc kompilieren, das keine Kommentare enthält (ich sollte hoffen) - dies bedeutet, dass Sie auch keinen Starttreffer erhalten, wenn das Skript bereits kompiliert ist.

MarkR
quelle
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
Mike Graham
1

Mein begrenztes Verständnis eines Interpreters besteht darin, dass er Programmausdrücke als Zeichenfolgen einliest und diese Zeichenfolgen in Code konvertiert.

Die meisten Interpreten lesen den Text (Code) und erstellen eine abstrakte Syntaxbaum-Datenstruktur.
Diese Struktur enthält keinen Code in Textform und natürlich auch keine Kommentare. Nur dieser Baum reicht aus, um Programme auszuführen. Aus Effizienzgründen gehen Dolmetscher jedoch noch einen Schritt weiter und erzeugen Bytecode. Und Python macht genau das.

Wir könnten sagen, dass der Code und die Kommentare in der Form, in der Sie sie geschrieben haben, einfach nicht vorhanden sind.
wenn das Programm ausgeführt wird. Nein, Kommentare verlangsamen die Programme zur Laufzeit nicht.

(*) Interpreter, die keine andere innere Struktur verwenden, um den Code als Text darzustellen,
dh einen Syntaxbaum, müssen genau das tun, was Sie erwähnt haben. Interpretieren Sie den Code zur Laufzeit immer wieder.

Nick Dandoulakis
quelle
0

Wie die anderen Antworten bereits angegeben haben, analysiert und kompiliert eine modern interpretierte Sprache wie Python zuerst die Quelle in Bytecode, und der Parser ignoriert die Kommentare einfach. Dies bedeutet eindeutig, dass ein Geschwindigkeitsverlust nur beim Start auftreten würde, wenn die Quelle tatsächlich analysiert wird.

Da der Parser Kommentare ignoriert, wird die Kompilierungsphase von den von Ihnen eingegebenen Kommentaren grundsätzlich nicht beeinflusst. Die Bytes in den Kommentaren selbst werden jedoch tatsächlich eingelesen und dann beim Parsen übersprungen. Dies bedeutet, wenn Sie eine verrückte Anzahl von Kommentaren haben (z. B. viele hundert Megabyte), würde dies den Interpreter verlangsamen. Andererseits würde dies auch jeden Compiler verlangsamen.

MAK
quelle
Ich bin mir nicht sicher, ob ich dies eine "interpretierte Sprache" im strengsten Sinne des Wortes nennen würde. So etwas wie dynamisch kompiliert oder JIT scheint angemessener.
3Dave
0

Ich frage mich, ob es darauf ankommt, wie Kommentare verwendet werden. Zum Beispiel ist dreifache Anführungszeichen eine Dokumentzeichenfolge. Wenn Sie sie verwenden, wird der Inhalt validiert. Ich bin vor einiger Zeit auf ein Problem gestoßen, bei dem ich eine Bibliothek in meinen Python 3-Code importiert habe ... Ich habe diesen Fehler bezüglich der Syntax für \ N erhalten. Ich habe mir die Zeilennummer angesehen und sie war in einem dreifachen Zitatkommentar enthalten. Ich war etwas überrascht. Neu in Python, ich hätte nie gedacht, dass ein Blockkommentar für Syntaxfehler interpretiert wird.

Einfach wenn Sie tippen:

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

Python 2 gibt keinen Fehler aus, aber Python 3 meldet: SyntaxError: (Unicode-Fehler) Der Codec 'unicodeescape' kann keine Bytes an Position 14-15 dekodieren: fehlerhaftes \ N-Zeichen-Escape

Python 3 interpretiert also offensichtlich das dreifache Anführungszeichen und stellt sicher, dass es eine gültige Syntax ist.

Wenn jedoch in einen einzeiligen Kommentar umgewandelt: # (dh \ Device \ NPF_ ..)
Es keine Fehler auf.

Ich frage mich, ob die Kommentare in dreifachen Anführungszeichen durch einzelne Zeilen ersetzt wurden, wenn sich die Leistung ändern würde.

kontinuierlicheqa
quelle
0

Diese Frage ist wirklich alt, aber nachdem ich die akzeptierte Antwort gelesen habe, die behauptet, dass sie keinen Einfluss auf die Ausführungszeit hat, was falsch ist, gebe ich Ihnen ein einfaches Beispiel, in dem Sie sehen und überprüfen können, inwieweit sie die Ausführungszeit tatsächlich beeinflusst.
Ich habe eine Datei namens constants.py. Es enthält alle verschiedenen Schachaktionen in einer Liste:

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

Die Liste LABELSenthält 2272 Elemente. In einer anderen Datei rufe ich auf:

import constants
np.array(constants.LABELS)

Ich habe es zehnmal gemessen und die Ausführung des Codes dauert ungefähr 0,597 ms. Jetzt habe ich die Datei geändert und neben jedes Element (2272 mal) einen Kommentar eingefügt:

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

Nachdem np.array(constants.LABELS)ich nun die Ausführungszeit zehnmal gemessen habe , habe ich eine durchschnittliche Ausführungszeit von 4,28 ms, also ungefähr siebenmal langsamer.
Daher wirkt sich dies auf die Ausführungszeit aus, wenn Sie viele Kommentare haben.

Code Papst
quelle
Was bedeutet eigentlich "Testen von np.array (constants.LABELS)"? Sehen Sie einen Unterschied bei kompilierten .pyc-Dateien?
Luper Rouch
@LuperRouch mit "Testen von np.array (constants.LABELS)" Ich meine, die Anweisung np.array(constant.LABELS)zehnmal auszuführen und die durchschnittliche Ausführungszeit der Anweisung zu messen. Ich werde das im Text klarstellen.
Code Papst
Wie führen Sie diese Anweisung aus? Vielleicht könnten Sie Ihr Test-Setup auf github verschieben, damit wir sehen können, wie genau Sie Ihren Test ausführen, da der Unterschied wahrscheinlich darauf zurückzuführen ist, dass Sie kompilierte .pyc-Dateien nicht wiederverwenden (wie gesagt, Kommentare wirken sich auf die Kompilierung aus Zeit, aber sie sollten die Ausführungszeit nicht beeinflussen).
Luper Rouch