Einige Basispunkte:
- Python-Methodenaufrufe sind aufgrund ihrer Interpretation "teuer" . Wenn Ihr Code einfach genug ist, hat das Auflösen von Python-Code theoretisch negative Auswirkungen, abgesehen von der Lesbarkeit und Wiederverwendung ( ein großer Gewinn für Entwickler, nicht so sehr für Benutzer ).
- Das Single-Responsibility-Prinzip (SRP) hält den Code lesbar und ist einfacher zu testen und zu warten.
- Das Projekt hat einen besonderen Hintergrund, in dem lesbarer Code, Tests und Zeitleistung gewünscht werden .
Beispielsweise ist ein Code wie dieser, der mehrere Methoden (x4) aufruft, langsamer als der folgende, der nur eine ist.
from operator import add
class Vector:
def __init__(self,list_of_3):
self.coordinates = list_of_3
def move(self,movement):
self.coordinates = list( map(add, self.coordinates, movement))
return self.coordinates
def revert(self):
self.coordinates = self.coordinates[::-1]
return self.coordinates
def get_coordinates(self):
return self.coordinates
## Operation with one vector
vec3 = Vector([1,2,3])
vec3.move([1,1,1])
vec3.revert()
vec3.get_coordinates()
Im Vergleich dazu:
from operator import add
def move_and_revert_and_return(vector,movement):
return list( map(add, vector, movement) )[::-1]
move_and_revert_and_return([1,2,3],[1,1,1])
Wenn ich so etwas parallelisieren will, ist es ziemlich objektiv, dass ich an Leistung verliere. Denken Sie daran, das ist nur ein Beispiel; In meinem Projekt gibt es mehrere Mini-Routinen mit Mathematik wie folgt: - Obwohl es viel einfacher ist, damit zu arbeiten, mögen es unsere Profiler nicht.
Wie und wo setzen wir die SRP ein, ohne die Leistung in Python zu beeinträchtigen, da sich ihre inhärente Implementierung direkt auf sie auswirkt?
Gibt es Workarounds wie eine Art Pre-Prozessor, der die Dinge für die Veröffentlichung vorbereitet?
Oder ist Python einfach schlecht darin, die Code-Aufschlüsselung insgesamt zu handhaben?
quelle
Antworten:
Leider ist Python langsam, und es gibt viele Anekdoten darüber, wie Menschen die Leistung drastisch steigern, indem sie Funktionen einfügen und ihren Code hässlich machen.
Es gibt ein Workaround, Cython, das eine kompilierte Version von Python und viel schneller ist.
--Bearbeiten Ich wollte nur einige der Kommentare und andere Antworten ansprechen. Obwohl der Schub von ihnen nicht vielleicht pythonspezifisch ist. aber allgemeinere Optimierung.
Optimieren Sie erst, wenn Sie ein Problem haben, und suchen Sie dann nach Engpässen
Generell guter Rat. Die Annahme ist jedoch, dass 'normaler' Code normalerweise performant ist. Dies ist nicht immer der Fall. Einzelne Sprachen und Frameworks haben jeweils ihre eigenen Besonderheiten. In diesem Fall Funktionsaufrufe.
Es ist nur ein paar Millisekunden, andere Dinge werden langsamer sein
Wenn Sie Ihren Code auf einem leistungsstarken Desktop-Computer ausführen, ist es Ihnen wahrscheinlich egal, solange Ihr Einzelbenutzercode in wenigen Sekunden ausgeführt wird.
Geschäftscode wird jedoch in der Regel für mehrere Benutzer ausgeführt und erfordert mehr als einen Computer, um die Last zu unterstützen. Wenn Ihr Code doppelt so schnell ausgeführt wird, bedeutet dies, dass Sie doppelt so viele Benutzer oder halb so viele Computer haben können.
Wenn Sie Eigentümer Ihrer Maschinen und Ihres Rechenzentrums sind, haben Sie im Allgemeinen einen hohen Overhead bei der CPU-Leistung. Wenn Ihr Code etwas langsam läuft, können Sie ihn absorbieren, zumindest bis Sie eine zweite Maschine kaufen müssen.
In Zeiten des Cloud Computing, in denen Sie nur genau die Rechenleistung verwenden, die Sie benötigen, und nicht mehr, fallen direkte Kosten für nicht performanten Code an.
Durch die Verbesserung der Leistung können die Hauptkosten für ein Cloud-basiertes Unternehmen drastisch gesenkt werden, und die Leistung sollte im Vordergrund stehen.
quelle
Viele mögliche Leistungsprobleme sind in der Praxis kein wirkliches Problem. Das Problem, das Sie ansprechen, kann eines davon sein. In der Umgangssprache bezeichnen wir das Sorgen um diese Probleme als vorzeitige Optimierung, ohne den Beweis zu erbringen, dass es sich tatsächlich um Probleme handelt .
Wenn Sie ein Front-End für einen Webdienst schreiben, wird Ihre Leistung durch Funktionsaufrufe nicht wesentlich beeinträchtigt, da die Kosten für das Senden von Daten über ein Netzwerk die Zeit für einen Methodenaufruf bei weitem überschreiten.
Wenn Sie eine enge Schleife schreiben, die sechzig Mal pro Sekunde einen Videobildschirm aktualisiert, ist dies möglicherweise von Bedeutung. Ich behaupte jedoch, dass Sie größere Probleme haben, wenn Sie versuchen, dies mit Python zu tun, ein Job, für den Python wahrscheinlich nicht geeignet ist.
Wie immer ist die Art und Weise, wie Sie herausfinden, zu messen. Führen Sie einen Leistungsprofiler oder einige Zeitgeber über Ihren Code aus. Sehen Sie, ob es in der Praxis ein echtes Problem ist.
Das Prinzip der einheitlichen Verantwortung ist kein Gesetz oder Auftrag. Es ist eine Richtlinie oder ein Prinzip. Beim Softwaredesign geht es immer um Kompromisse. es gibt keine absoluten. Es ist nicht ungewöhnlich, die Lesbarkeit und / oder Wartbarkeit für die Geschwindigkeit abzuwägen, sodass Sie möglicherweise SRP auf dem Altar der Leistung opfern müssen. Aber machen Sie diesen Kompromiss erst, wenn Sie wissen, dass Sie ein Leistungsproblem haben.
quelle
Zunächst einige Erläuterungen: Python ist eine Sprache. Es gibt verschiedene Interpreter, die in der Python-Sprache geschriebenen Code ausführen können. Auf die Referenzimplementierung (CPython) wird normalerweise verwiesen, wenn von "Python" die Rede ist, als ob es sich um eine Implementierung handelt. Es ist jedoch wichtig, genau zu sein, wenn es um Leistungsmerkmale geht, da sie sich zwischen den Implementierungen stark unterscheiden können.
Fall 1.) Wenn Sie reinen Python-Code haben (<= Python Language Version 3.5, 3.6 unterstützt Beta-Level), der nur auf reinen Python-Modulen basiert, können Sie SRP überall verwenden und PyPy zum Ausführen verwenden. PyPy ( https://morepypy.blogspot.com/2019/03/pypy-v71-released-now-uses-utf-8.html ) ist ein Python-Interpreter, der über einen Just-in-Time-Compiler (JIT) verfügt und Funktionen entfernen kann Rufen Sie den Overhead auf, solange er genügend Zeit zum "Aufwärmen" hat, indem Sie den ausgeführten Code verfolgen (einige Sekunden IIRC). **
Wenn Sie nur den CPython-Interpreter verwenden dürfen, können Sie die langsamen Funktionen in in C geschriebene Erweiterungen extrahieren, die vorkompiliert werden und keinen Interpreter-Overhead verursachen. Sie können SRP immer noch überall verwenden, aber Ihr Code wird zwischen Python und C aufgeteilt. Ob dies für die Wartbarkeit besser oder schlechter ist, als wenn Sie SRP selektiv aufgeben, sich aber nur an Python-Code halten, hängt von Ihrem Team ab, aber ob Sie leistungskritische Bereiche haben Code ist zweifellos schneller als selbst der optimierteste reine Python-Code, der von CPython interpretiert wird. Viele der schnellsten mathematischen Bibliotheken von Python verwenden diese Methode (numpy und scipy IIRC). Welches ist ein schöner Einstieg in Fall 2 ...
Fall 2.) Wenn Sie Python-Code haben, der C-Erweiterungen verwendet (oder sich auf Bibliotheken stützt, die C-Erweiterungen verwenden), ist PyPy möglicherweise nützlich oder nicht, je nachdem, wie sie geschrieben wurden. Siehe http://doc.pypy.org/en/latest/extending.html Informationen finden Die Zusammenfassung lautet jedoch, dass CFFI nur einen minimalen Overhead hat, während CTypes langsamer ist (die Verwendung mit PyPy ist möglicherweise sogar langsamer als CPython).
Cython ( https://cython.org/ ) ist eine weitere Option, mit der ich nicht so viel Erfahrung habe. Ich erwähne es der Vollständigkeit halber, damit meine Antwort "für sich" stehen kann, beanspruche aber kein Fachwissen. Aufgrund meiner eingeschränkten Nutzung hatte ich das Gefühl, dass ich mich mehr anstrengen musste, um die gleichen Geschwindigkeitsverbesserungen zu erzielen, die ich mit PyPy "kostenlos" erreichen konnte, und wenn ich etwas Besseres als PyPy brauchte, war es genauso einfach, meine eigene C-Erweiterung zu schreiben ( Das hat den Vorteil, wenn ich den Code an einer anderen Stelle wiederverwende oder einen Teil davon in eine Bibliothek extrahiere. Mein gesamter Code kann weiterhin unter jedem Python-Interpreter ausgeführt werden und muss nicht von Cython ausgeführt werden.
Ich habe Angst davor, in Cython "eingesperrt" zu sein, während jeder für PyPy geschriebene Code auch unter CPython laufen kann.
** Einige zusätzliche Hinweise zu PyPy in der Produktion
Seien Sie sehr vorsichtig, wenn Sie Entscheidungen treffen, die den praktischen Effekt haben, dass Sie sich in PyPy in einer großen Codebasis "einschließen". Da einige (sehr beliebte und nützliche) Bibliotheken von Drittanbietern aus den oben genannten Gründen nicht gut funktionieren, kann es später zu sehr schwierigen Entscheidungen kommen, wenn Sie feststellen, dass Sie eine dieser Bibliotheken benötigen. Meine Erfahrung besteht hauptsächlich darin, mit PyPy einige (aber nicht alle) Mikrodienste zu beschleunigen, die in einer Unternehmensumgebung, in der die Komplexität unserer Produktionsumgebung vernachlässigbar ist, leistungsabhängig sind (wir haben bereits mehrere Sprachen implementiert, einige mit unterschiedlichen Hauptversionen wie 2.7 vs 3.5 läuft sowieso).
Ich habe festgestellt, dass sowohl PyPy als auch CPython mich regelmäßig gezwungen haben, Code zu schreiben, der sich nur auf Garantien stützt, die von der Sprachspezifikation selbst gegeben wurden, und nicht auf Implementierungsdetails, die jederzeit geändert werden können. Möglicherweise stellt das Nachdenken über solche Details eine zusätzliche Belastung dar, aber ich fand es in meiner beruflichen Entwicklung wertvoll und finde es "gesund" für das gesamte Python-Ökosystem.
quelle