Um eine Geschwindigkeitssteigerung für mein Python-Programm zu erhalten, sollte ich einen separaten Thread oder einen separaten Prozess für die Protokollierung erstellen?

8

Um eine Geschwindigkeitssteigerung für mein Python-Programm zu erhalten, sollte ich einen separaten Thread oder einen separaten Prozess für die Protokollierung erstellen? Mein Programm verwendet viel Protokollierung und ich bin mir nicht sicher, ob Threading wegen GIL geeignet ist. Viele Ressourcen deuten darauf hin, dass es für E / A in Ordnung sein sollte. Ich denke, dass Logging I / O ist, aber ich bin mir nicht sicher, was "sollte gut sein" bedeutet für die meisten Ressourcen da draußen. Ich brauche nur Geschwindigkeit.

    
user2675516 13.09.2017, 17:50
quelle

2 Antworten

8

Bevor Sie versuchen, ein Programm zu optimieren, sollten Sie einige Dinge tun.

Zunächst sollten Sie Ihre Programme profilieren . Sie könnten z.B. Verwenden Sie line_profiler .

Wenn sich herausstellt, dass Ihre Software viel Zeit für die Protokollierung aufwendet, gibt es zwei einfache Möglichkeiten.

  • Legen Sie den loglevel im Produktionscode fest, damit keine oder wenige (er) Nachrichten protokolliert werden. Es wird immer noch etwas Overhead übrig bleiben, aber es sollte sehr reduziert werden.
  • Verwenden Sie mechanische Mittel (wie sed oder grep ), um vollständig die Protokollierungsaufrufe aus dem Produktionscode zu entfernen. Wenn dies die Geschwindigkeit / den Durchsatz Ihres Programms nicht verbessert, war die Protokollierung kein Problem.

Wenn keine von beiden geeignet ist und die Protokollierung einen erheblichen Teil der Zeit Ihres Programms ausmacht, können Sie versuchen, eine Thread- oder prozessbasierte Protokollierung zu implementieren.

Wenn Sie threading für die Protokollierung verwenden möchten, benötigen Sie eine Liste und eine Sperre. Die Funktion, die vom Hauptthread aufgerufen wird, um die Protokollierung durchzuführen, ergreift die Sperre, fügt den zu protokollierenden Text an die Liste an und gibt die Sperre frei. Der zweite Thread wartet auf die Sperre, ergreift die Sperre, öffnet ein paar Elemente aus der Liste, gibt die Sperre frei und schreibt die Elemente in eine Datei. Da die GIL sicherstellt, dass immer nur ein Thread Python-Bytecode ausführt, wird dies die Leistung Ihres Programms etwas verringern; Ein Teil seiner Zeit wird damit verbracht, den Bytecode vom Logging-Thread auszuführen.

Die Verwendung von multiprocessing ist etwas anders, da Sie wahrscheinlich z. a Queue , um Protokollierungsnachrichten vom Hauptprozess an den Protokollierungsprozess zu senden. Der Protokollierungsprozess nimmt Elemente aus der Warteschlange und schreibt sie auf die Festplatte. Dies bedeutet, dass der Zeitaufwand für das Schreiben der Protokollierungsaktionen auf die Festplatte in einem anderen Programm verbracht wird. Aber es gibt auch einige Gemeinkosten, die mit der Verwendung einer Warteschlange verbunden sind.

Sie müssten messen um zu sehen, welche Methode in Ihrem Programm weniger Zeit benötigt.

    
Roland Smith 17.09.2017 15:42
quelle
0

Ich gehe von diesen Annahmen aus:

  • Sie haben bereits festgestellt, dass Ihre Protokollierung Ihr Programm blockiert.
  • Sie haben einen guten Grund, warum Sie protokollieren, was Sie protokollieren.

Die wahrgenommene Langsamkeit ist wahrscheinlich auf die Erfolgs- oder Fehlerbestätigung von der Protokollierungsaktion zurückzuführen. Um dieses "Command Queuing" zu vermeiden, führen Sie die Aufrufe zu einem separaten Prozess asynchron durch und überspringen Sie den Callback. Dies kann am Ende verbrauchen mehr Ressourcen, aber dies wird den Rückstand in Ihrem Hauptprogramm zu verringern. Nodejs behandelt das natürlich oder Sie können Ihren eigenen Python-Listener rollen. Da dies ein separater Prozess sein wird. Sie können die Protokollierungsfunktion Ihrer anderen Programme auf diese umleiten. Sie können sogar eine separate Maschine für diesen Workload einrichten.

    
Robert Co 23.09.2017 15:13
quelle