Filter mit multiprocessing ist langsamer als ohne
Verfasst: Mittwoch 21. November 2018, 11:21
Hallo zusammen,
ich habe noch nie einen Anwendungsfall gehabt, bei dem ich dachte, das multiprocessing mir einen signifikanten Geschwindigkeitsvorteil bieten könnte, daher fange ich gerade das erste Mal an mich damit zu beschäftigen. Allerdings führen meine bisherigen Bemühungen dazu das mein multiprocessing code langsamer läuft als mein normaler.
Ich habe eine mehrere GB (~17) große logdatei. Ich möchte nun einen filter bauen, der nur solche Zeilen ausgibt, welche sich in einem bestimmten Zeitbereich befinden. Exemplarisch sehen diese Logzeilen so aus:
Der 2. Zeitstempel ist der für mich interessante (2018-10-31 16:11:56,755) und ist in CEST. Ich leite diese Logzeilen per Pipe unter Linux an mein Script weiter (zcat logfile.gz | python meinscript.py). Um dabei nur solche Zeilen auszugeben, bei denen sich dieser besagte 2. Zeitstempel zwischen 17:00:00 und 17:30:00 JST befindet, sieht mein single-process Ansatz folgendermaßen aus (Python 3.6):
Das ganze funktioniert auch und dauert bei 5.930.000 Zeilen (stark gekürztes Test-Log) auf meinem Rechner ca. 7 Minuten.
Mein multiprocessing - Ansatz sieht folgendermaßen aus:
In der Prozessübersicht meines Testsystemes (4 cores) sehe ich auch das dieser Code insgesamt 8 Prozesse forked. Allerdings benötigt dieser zur Auswertung derselben Eingabedatei ca 12 Minuten; also fast doppelt so lange. Ich habe zwar nicht erwartet das es genau 1/4 des single-processing Ansatzes dauert, jedoch schon das es bei 4 Prozessen schneller geht.
Was mache ich falsch?
ich habe noch nie einen Anwendungsfall gehabt, bei dem ich dachte, das multiprocessing mir einen signifikanten Geschwindigkeitsvorteil bieten könnte, daher fange ich gerade das erste Mal an mich damit zu beschäftigen. Allerdings führen meine bisherigen Bemühungen dazu das mein multiprocessing code langsamer läuft als mein normaler.
Ich habe eine mehrere GB (~17) große logdatei. Ich möchte nun einen filter bauen, der nur solche Zeilen ausgibt, welche sich in einem bestimmten Zeitbereich befinden. Exemplarisch sehen diese Logzeilen so aus:
Code: Alles auswählen
2018-10-31T16:12:01+01:00 apphost96 TSWITCH-APP08: 2018-10-31 16:11:56,755 [INFO] ...
Code: Alles auswählen
from datetime import datetime, timedelta
from pytz import timezone
import sys
import re
def filter_line(from_dt_obj, to_dt_obj, cest_tz_obj, line):
line = line.strip()
try:
line_time = cest_tz_obj.localize(datetime.strptime(f'{line.split(" ")[3]}:{line.split(" ")[4].split(",")[0]}',
'%Y-%m-%d:%H:%M:%S'))
except (IndexError, ValueError):
return None
if from_dt_obj <= line_time <= to_dt_obj:
print(line)
jst_tz = timezone('Japan')
cest_tz = timezone('Europe/Berlin')
from_dt = jst_tz.localize(datetime(year=2018, month=11, day=1))
to_dt = from_dt + timedelta(minutes=30)
for line in sys.stdin:
filter_line(from_dt, to_dt, cest_tz, re_proxy_pattern, line)
Mein multiprocessing - Ansatz sieht folgendermaßen aus:
Code: Alles auswählen
from datetime import datetime, timedelta
from pytz import timezone
from multiprocessing import Pool
from functools import partial
import sys
import re
def filter_line(from_dt_obj, to_dt_obj, cest_tz_obj, line):
line = line.strip()
try:
line_time = cest_tz_obj.localize(datetime.strptime(f'{line.split(" ")[3]}:{line.split(" ")[4].split(",")[0]}',
'%Y-%m-%d:%H:%M:%S'))
except (IndexError, ValueError):
return None
if from_dt_obj <= line_time <= to_dt_obj:
print(line)
jst_tz = timezone('Japan')
cest_tz = timezone('Europe/Berlin')
from_dt = jst_tz.localize(datetime(year=2018, month=11, day=1))
to_dt = from_dt + timedelta(minutes=30)
func = partial(filter_line, from_dt, to_dt, cest_tz, re_proxy_pattern)
with Pool() as pool:
for x in pool.imap(func, sys.stdin):
pass
Was mache ich falsch?