Python ist langsam, dies sind häufige Gründe: „Weil es eine GIL (Global Interpreter Lock) ist“, „Weil es eine interpretierte Sprache ist, keine kompilierte Sprache“, „Weil es eine dynamisch typisierte Sprache ist“.
Empfohlener Kurs: Java-Tutorial.
Welcher Grund hat den größten Einfluss auf die Leistung?
„Weil es die GIL ist“
Die CPUs moderner Computer verfügen über mehrere Kerne und manchmal sogar mehrere Prozessoren. Um die gesamte Rechenleistung zu nutzen, definiert das Betriebssystem eine zugrunde liegende Struktur namens Thread, und ein Prozess (z. B. der Chrome-Browser) kann mehrere Threads generieren, um Systemanweisungen über Threads auszuführen. Wenn ein Prozess viele CPUs nutzt, wird die Rechenlast auf diese Weise auf mehrere Kerne verteilt, sodass die meisten Anwendungen ihre Aufgaben letztendlich schneller erledigen können.
Zum jetzigen Zeitpunkt sind in meinem Chrome-Browser 44 Threads geöffnet. Darüber hinaus unterscheiden sich die Thread-Struktur und die API von POSIX-basierten Betriebssystemen (wie Mac OS und Linux) von denen von Windows-Betriebssystemen. Das Betriebssystem ist auch für die Thread-Planung verantwortlich.
Wenn Sie noch kein Multithread-Programm geschrieben haben, sollten Sie das Konzept von Sperren verstehen. Im Gegensatz zu einem Single-Thread-Prozess möchten Sie bei der Multi-Thread-Programmierung sicherstellen, dass beim Ändern von Variablen im Speicher nicht mehrere Threads versuchen, gleichzeitig dieselbe Speicheradresse zu ändern oder darauf zuzugreifen.
CPython reserviert beim Erstellen einer Variablen Speicher und verwendet dann einen Zähler, um die Anzahl der Verweise auf die Variable zu zählen. Dieses Konzept wird als „Referenzzählung“ bezeichnet. Wenn die Anzahl der Referenzen 0 ist, kann die Variable aus dem System freigegeben werden. Auf diese Weise beansprucht das Erstellen „temporärer“ Variablen (z. B. im Kontext einer for-Schleife) nicht den Speicher Ihrer Anwendung.
Das Problem besteht darin, dass CPython den Referenzzähler sperren muss, wenn die Variable von mehreren Threads gemeinsam genutzt wird. Es gibt eine „globale Interpretersperre“, die die Thread-Ausführung sorgfältig steuert. Unabhängig von der Anzahl der Threads kann der Interpreter jeweils nur eine Operation ausführen.
Welche Auswirkungen hat dies auf die Leistung von Python-Anwendungen?
Wenn die Anwendung Single-Threaded und Single-Interpreter ist, hat dies keinen Einfluss auf die Geschwindigkeit. Das Entfernen der GIL hat keinen Einfluss auf die Leistung des Codes.
Aber wenn Sie einen Interpreter (einen Python-Prozess) verwenden möchten, um Parallelität über Threads zu erreichen, und die Threads IO-intensiv sind (das heißt, es gibt viele Netzwerk-Ein- und -Ausgaben oder Festplatten-Ein- und -Ausgaben). ), dann findet der folgende GIL-Wettbewerb statt:
Wenn eine Webanwendung (wie Django) WSGI verwendet, wird jede an die Webanwendung gesendete Anfrage gesendet Wird von einem separaten Python-Interpreter ausgeführt. Daher gibt es nur eine Sperre pro Anfrage. Da der Python-Interpreter sehr langsam startet, unterstützen einige WSGI-Implementierungen den „Daemon-Modus“, um den Python-Prozess lange am Laufen zu halten.
„Weil es eine interpretierte Sprache ist“
Ich habe diesen Grund schon oft gehört und finde, dass er die tatsächliche Funktionsweise von CPython zu stark vereinfacht. Wenn Sie python myscript.py im Terminal schreiben, initiiert CPython eine lange Kette von Vorgängen, einschließlich Lesen, lexikalischer Analyse, Syntaxanalyse, Kompilierung, Interpretation und Ausführung. Der entscheidende Punkt dieses Prozesses besteht darin, dass während der Kompilierungsphase eine .pyc-Datei generiert wird und der Bytecode in eine Datei unter __pycache__/ (wenn es sich um Python 3 handelt) oder in dasselbe Verzeichnis wie der Quellcode geschrieben wird (Python 2). Dies gilt nicht nur für die von Ihnen geschriebenen Skripte, sondern auch für den gesamten Code, den Sie importieren, einschließlich der Module von Drittanbietern.
In den meisten Fällen (es sei denn, Sie schreiben Code, der nur einmal ausgeführt wird) interpretiert Python den Bytecode und führt ihn lokal aus. Vergleichen Sie dies mit Java und C#.NET:
Java kompiliert Quellcode in eine „Zwischensprache“, und dann liest die Java Virtual Machine den Bytecode und kompiliert ihn im laufenden Betrieb in Maschinencode. Dasselbe gilt für .NET CIL. Die Common Language Runtime (CLR) von .NET verwendet Just-in-Time-Kompilierung, um Bytecode in Maschinencode zu kompilieren.
Da beide eine virtuelle Maschine und eine Art Bytecode verwenden, warum ist Python in Leistungstests so viel langsamer als Java und C#? Der erste Grund ist, dass .NET und Java Just-in-Time (JIT) kompiliert werden.
JIT (Just-in-time) erfordert eine Zwischensprache, um den Code in kleine Teile (oder Frames) zu unterteilen. Ahead of Time (AOT) bedeutet, dass der Compiler den Quellcode in Code übersetzt, den die CPU verstehen kann, bevor er ihn ausführt.
JIT selbst beschleunigt die Ausführung nicht, da es dieselbe Bytecodesequenz ausführt. JIT kann jedoch zur Laufzeit Optimierungen vornehmen. Ein guter GIT-Optimierer kann die am häufigsten ausgeführten Teile Ihrer Anwendung finden, die sogenannten „Hot Spots“. Diese Bytecodes werden dann optimiert und durch effizienteren Code ersetzt.
Das bedeutet, dass Ihre Anwendung viel schneller ist, wenn sie etwas wiederholt ausführt. Vergessen Sie außerdem nicht, dass sowohl Java als auch C# stark typisierte Sprachen sind, sodass der Optimierer mehr Annahmen über den Code treffen kann.
„Weil es eine dynamisch typisierte Sprache ist“
„Statische Typ“-Sprachen erfordern, dass der Typ einer Variablen bei der Definition angegeben werden muss, z. B. C, C++, Java, C# und Go usw.
Obwohl es das Konzept des Typs auch in dynamisch typisierten Sprachen gibt, ist der Typ der Variablen dynamisch.
a = 1 a = "foo"
In diesem Beispiel definiert Python eine zweite Variable mit demselben Namen und Typ str und gibt gleichzeitig den von der ersten Instanz von a belegten Speicher frei.
Statisch typisierte Sprachen sind nicht dazu gedacht, Menschen zu quälen, sie sind so konzipiert, weil CPUs so funktionieren. Wenn eine Operation letztendlich in eine einfache Binäroperation umgewandelt wird, müssen sowohl Objekte als auch Typen in Datenstrukturen auf niedriger Ebene umgewandelt werden.
Python erledigt das alles für Sie, aber Sie haben sich nie darum gekümmert und müssen sich auch nicht darum kümmern.
Python ist nicht langsam, weil keine Typen definiert werden müssen. Das Design von Python ermöglicht es Ihnen, alles dynamisch zu gestalten. Sie können Objektmethoden zur Laufzeit ersetzen und zugrunde liegende Systemaufrufe zur Laufzeit patchen. Fast alles ist möglich.
Und dieses Design macht es schwierig, Python zu optimieren.
Wird Python durch die dynamische Typisierung Python langsamer?
Der Vergleich und die Konvertierung von Typen ist teuer. Dynamisch typisierte Sprachen, die den Typ
jedes Mal überprüfen, wenn sie gelesen, geschrieben oder referenziert werden, sind schwer zu optimieren. Der Grund, warum viele Alternativen zu Python so schnell sind, liegt darin, dass sie Komfort zugunsten der Leistung opfern.
Zum Beispiel kombiniert Cython (http://cython.org/) die statische Typisierung von C und Python, um die Typen im Code bekannt zu machen, wodurch der Code optimiert und in der Lage ist um eine 84-fache Leistungssteigerung zu erzielen
Zusammenfassung
Der Hauptgrund, warum Python langsam ist, liegt in seiner Dynamik und Vielfalt. Es kann zur Lösung einer Vielzahl von Problemen verwendet werden, für die meisten Probleme gibt es jedoch besser optimierte und schnellere Lösungen.
Python-Anwendungen verfügen jedoch auch über viele Optimierungsmaßnahmen, z. B. die Verwendung von Asynchronität, das Verständnis von Leistungstesttools und die Verwendung mehrerer Interpreter.
Für Anwendungen, bei denen die Startzeit keine Rolle spielt und der Code möglicherweise von JIT profitiert, sollten Sie die Verwendung von PyPy in Betracht ziehen.
Für Teile des Codes, bei denen die Leistung wichtig ist und die Variablen größtenteils statisch typisiert sind, sollten Sie die Verwendung von Cython in Betracht ziehen.
Das obige ist der detaillierte Inhalt vonWarum ist Java schneller als Python?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!