Verwenden Sie diese Tipps, um Ihren Code zu analysieren und herauszufinden, wo er am effizientesten oder am wenigsten effizient ist.
Da es in Python „mehr als eine Möglichkeit“ gibt, kann es schwierig sein, für einige Aufgaben den speichereffizientesten Ansatz zu finden. Hier kann ein Speicherprofiler helfen. Neben der Verfolgung von Lecks hilft die Schätzung des Speicherprofils Ihres Codes dabei, festzustellen, welcher Code speichereffizient ist.
Unabhängig davon, ob Sie ein Modell für maschinelles Lernen oder eine Website mit Python entwickeln, können Sie das Speicherprofil für Skripte, einzelne Codezeilen oder Funktionen schätzen.
Die Schätzung des Speicherprofils Ihrer gesamten Codebasis ist möglicherweise unpraktisch, da dies Ihre Anwendung erheblich verlangsamen kann. Am besten erstellen Sie stattdessen gezielt ein Profil für Funktionen oder Methoden, von denen Sie vermuten, dass sie mehr Speicher verbrauchen. Aber selbst wenn Sie dies für Ihre gesamte Anwendung tun möchten, möchten Sie möglicherweise ein isoliertes Modul dafür reservieren.
Es gibt viele Profilierungsbibliotheken in Python. Einige der beliebtesten sind Memory_profiler, psutil, Tracemalloc, Und Pympler. Dieses Tutorial verwendet Memory_profiler Und psutil.
Während psutil ist ideal für die Schätzung des Gesamtspeicherverbrauchs einer Methoden- oder Funktionsausführung, Memory_profiler Bietet detailliertere Informationen zur Speichernutzung, einschließlich zeilenweiser und funktionaler Nutzungstrends auf Funktionsebene im Laufe der Zeit.
Um zu beginnen, installieren Sie Memory_profiler in Ihre virtuelle Python-Umgebung. Dies wird auch installiert psutil.
pip installiere den Memory_Profiler
Ermitteln Sie die Größe eines Objekts im Speicher
Sie können mit der Speicherprofilierung beginnen, indem Sie zunächst die Größe eines Objekts berechnen, das Sie im Speicher verwenden möchten.
Diese Art der Profilerstellung ist zu Beginn der Entwicklung hilfreich, wenn versucht wird, zu bestimmen, welcher Objekttyp in einem Programm verwendet werden soll.
Wenn Sie beispielsweise nicht entscheiden können, welche Methoden Sie zur Lösung einer Aufgabe verwenden sollen, sagen wir, welche geeignet sind Wenn Sie einen Python-Datentyp verwenden, können Sie die Größe jedes einzelnen in Bytes ermitteln, um zu bestimmen, welcher für Ihre Verwendung einfacher ist Fall.
Der sys.getsizeof Die integrierte Methode ist hier praktisch:
importieren sys
drucken(f"Listengröße: {sys.getsizeof([])} Bytes")
drucken(f"Wörterbuchgröße: {sys.getsizeof (dict)} Bytes")
drucken(f"Tupelgröße: {sys.getsizeof(())} Bytes")
drucken(f"Größe festlegen: {sys.getsizeof({})} Bytes")
Hier ist die Ausgabe:
Sie können auch die verwenden sys.getsizeof Methode zum Vergleichen der Speichergröße einer integrierten und einer benutzerdefinierten Funktion.
Vergleichen Sie beispielsweise diese benutzerdefinierte Längenfunktion damit verwendet eine Python-for-Schleife mit dem eingebauten len Funktion:
importieren sys
defgetLength(wiederholbar):
zählen = 0für ich In wiederholbar:
zählen +=1zurückkehren zählen
drucken(f"Eingebaute Längenfunktion: {sys.getsizeof (len)} Bytes")
drucken(f"Benutzerdefinierte Längenfunktion: {sys.getsizeof (getLength)} Bytes")
Der obige Code liefert die folgende Ausgabe:
Allerdings während sys.getsizeof misst die Größe eines Objekts im Speicher, berücksichtigt nur das Objekt selbst und nicht diejenigen, die darauf verweisen. Dafür benötigen Sie eine detailliertere Profilierungsmethode.
Finden Sie das Speicherprofil einer Python-Funktion
Mit dem können Sie ein detaillierteres Speicherprofil jeder Codezeile einer Funktion erhalten Memory_profiler Paket. Dazu gehört das Hinzufügen der @Profil Dekorator für Ihre Funktion oder Methode:
Pandas importieren
Numpy importieren
aus dem Memory_profiler-ImportprofilKlasse Manipulieren:
@Profil
def manipulierenDaten (selbst):
df = Pandas. DataFrame({
'A' :[0, 3, numpy.nan, 10, 3, numpy.nan],
'B': [numpy.nan, „Pandas“, numpy.nan, „Pandas“, „Python“, „JavaScript“],
})df.fillna (method='bfill', inplace=True)
df.fillna (method='ffill', inplace=True)
return str (df)
manip = Manipulieren()
print (manip.manipulateData())
Der obige Code gibt ein detailliertes Speicherprofil jeder Codezeile in der Funktion an, wie gezeigt:
Der Mem-Nutzung Die Spalte gibt die Speichernutzung für eine bestimmte Codezeile an, während die Zuwachs Die Spalte zeigt den von jeder Zeile verursachten Overhead. Der Auftreten Die Spalte definiert, wie oft eine Codezeile Speicher zuweist oder freigibt.
In der obigen Ausgabe kam Zeile 11 beispielsweise zweimal mit einem Speicherinkrement von 0,1 MiB (Mebibyte) vor, wodurch sich die Speichernutzung auf 55,4 MiB erhöhte. Die Zeilen 19 und 22 trugen ebenfalls 0,2 MiB bzw. 0,3 MiB bei, was einer Gesamtspeichernutzung von 55,9 MiB entspricht.
Finden Sie das Speicherprofil eines Python-Skripts anhand des Zeitstempels
Sie können das Speicherprofil eines gesamten Python-Skripts auch mit schätzen Memory_profiler durch Ausführen des mprof Befehl im Terminal wie gezeigt:
mprof führt script_name.py aus
Der obige Befehl tastet das angegebene Skript alle 0,1 Sekunden ab und erstellt automatisch ein .dat Datei in Ihrem aktuellen Projektverzeichnis.
Die Zahlen, die folgen MEM Notation sind die Speichernutzungsprofile des Python-Skripts in einem bestimmten Zeitintervall. Die letzten Zahlen auf der rechten Seite stellen den Zeitstempel dar, den der Profiler für jede Speichernutzung erfasst hat.
Sie können auch eine grafische Darstellung des Speicherprofils erhalten. Dies erfordert eine Installation von matplotlib:
pip matplotlib installieren
Führen Sie nach der Installation das aus mprof Befehl etwa so:
mprof-Diagramm
Hier ist die Ausgabe in diesem Fall:
Führen Sie das Skriptspeicherprofil in einer dedizierten Python-Datei aus
Möglicherweise möchten Sie ein Profil für verschiedene Python-Skripte erstellen. Du kannst das Verwendung eines dedizierten Python-Moduls über Pythons Unterprozess.
Auf diese Weise können Sie Ihren Speicherprofiler von Ihrer Codebasis trennen und die Diagrammausgabe lokal speichern:
importieren Unterprozess
subprocess.run([
'mprof', 'laufen', '--include-children', 'missing.py'
])
# Speichern Sie die Plotausgabe lokal
subprocess.run(['mprof', 'Parzelle', '--output=output.jpg'])
Um das Speicherprofil des Skripts auszuführen, müssen Sie nur die Python-Datei ausführen, die den obigen Code enthält. Dadurch wird ein Speicherprofildiagramm erstellt (Ausgabe.jpg) im Dateiverzeichnis:
Ermitteln Sie die von einer Funktionsausführung verwendete Speichermenge
Sie können das Gesamtspeicherprofil einer Methode oder Funktion während der Ausführung mithilfe von ermitteln psutil Paket.
Zum Beispiel, um den Vorgänger zu profilieren Pandas DataFrame-Manipulation Methode in einer anderen Python-Datei:
importieren psutil
importieren sys
importieren os
sys.path.append (sys.path[0] + "/..")# Importieren Sie die Klasse, die Ihre Methode enthält
aus Irgendein Code fehlt importieren Manipulieren# Instanziiert die Klasse
manip = Manipulieren()Prozess = psutil. Prozess (os.getpid())
initial_memory =process.memory_info().rss# Führen Sie die Zielmethode aus:
manip.manipulateData()
# Speicherinformationen nach der Ausführung abrufen
final_memory =process.memory_info().rss
memory_consumed = final_memory – initial_memory
Memory_consumed_mb = Memory_consumed / (1024 * 1024)
drucken(f"Von der Funktion verbrauchter Speicher: {memory_consumed_mb:.2F} MB")
Das Obige schätzt das Gesamtspeicherprofil der Methode in Megabyte (MB) wie folgt:
Finden Sie das Speicherprofil einer Codezeile im Jupyter Notebook
Wenn Sie iPython in Jupyter Notebook verwenden, können Sie das Speicherprofil eines Einzeilers mithilfe von berechnen Memory_profiler. Sie müssen nur laden Memory_profiler in einer Zelle. Dann fügen Sie die hinzu %memit Fügen Sie Ihrem Code in nachfolgenden Zellen eine magische Funktion hinzu. Dies gibt den Spitzenspeicher und die erhöhte Größe des Codes zurück.
Diese Methode funktioniert nicht mit regulären Python-Skripten außer iPython in Jupyter Notebook.
Zum Beispiel:
Sie können auch die verwenden %memit magische Funktion in Jypyter Notebook zum Profilieren des Speichers einer Funktion zur Laufzeit:
Verbessern Sie Ihre Speichereffizienz in Ihrem Python-Code
Angesichts der anspruchsvollen Datenerfassungsaufgaben, für die wir Python häufig verwenden, muss jede Codezeile angemessen optimiert werden, um die Speichernutzung zu verwalten. Während Python über viele integrierte Python-Funktionen verfügt, führen nicht referenzierte Objekte zu Speicherverlusten.
Wenn Sie jede funktionierende Python-Syntax in Ihre Codebasis eingefügt haben, ohne die Speichernutzung zu berücksichtigen, sollten Sie vielleicht einen Blick zurück werfen, bevor Sie zu weit gehen.