просто немного поиграю, и я вижу, multiprocessing
требуется время, чтобы разрушить Пул, но в остальном не так много в нем
тестовый код:
from time import time, sleep
from multiprocessing.pool import Pool, ThreadPool
from threading import Thread
N_WORKER_JOBS = 10
def worker(x):
# print("working on", x)
sleep(0.1)
def mp_proc(fn, n):
start = time()
with Pool(N_WORKER_JOBS) as pool:
t1 = time() - start
pool.map(fn, range(n))
start = time()
t2 = time() - start
print(f'Pool creation took {t1*1000:.2f}ms, teardown {t2*1000:.2f}ms')
def mp_threads(fn, n):
start = time()
with ThreadPool(N_WORKER_JOBS) as pool:
t1 = time() - start
pool.map(fn, range(n))
start = time()
t2 = time() - start
print(f'ThreadPool creation took {t1*1000:.2f}ms, teardown {t2*1000:.2f}ms')
def threads(fn, n):
threads = []
for i in range(n):
t = Thread(target=fn, args=(i,))
threads.append(t)
t.start()
for t in threads:
t.join()
for test in [mp_proc, mp_threads, threads]:
times = []
for _ in range(7):
start = time()
test(worker, 10)
times.append(time() - start)
times = ', '.join(f'{t*1000:.2f}' for t in times)
print(f'{test.__name__} took {times}ms')
Я получаю следующее время (Python 3.7.3, Linux 5.0.8):
mp_proc
~ 220 мс
mp_threads
~ 200 мс
threads
~ 100 мс
однако время разрыва составляет все ~ 100 мс, что приводит все в основном в соответствие.
Я возился с ведением журнала и в источнике, и, кажется, это из-за того, что _handle_workers
проверяет только каждые 100 мс (он проверяет состояние, затем спит 0,1 секунды).
с этим знанием я могу сменить код на 0,095 секунды, тогда все будет в пределах 10% друг от друга. Кроме того, учитывая, что это только один раз при сносе пула, легко организовать, чтобы это не происходило во внутреннем цикле