Administrator
Published on 2022-07-29 / 1,252 Visits
0
0

python多线程速度慢分析

需求

需要快速创建1000张图片

单线程

我们先来试试以下代码直接单线程创建

import time
startTime = time.time()
for i in range(1000):
    startTimeTask = time.time()
    open("./img/"+str(i)+".jpg","wb")
    print(time.time()-startTimeTask)
print(time.time()-startTime)

图片-1659063753794
图片-1659063038169

创建一张图片平均时间0.01436秒 ,总时间14.36秒,平均速率约69.64张/秒,磁盘io使用率也空闲很多,速度对比其他语言极慢。

去除大量的print看看(因为python print也是比较耗时的)

import time
startTime = time.time()
for i in range(1000):
    open("./img/"+str(i)+".jpg","wb")
print(time.time()-startTime)

图片-1659063670468
图片-1659063574022

看起来去掉print快了4秒,但算下来每秒也就100张,依然还是很慢

多线程

import threadpool
import time

def func(num):
    num = num*100
    endNum =num+100
    for i in range(num,endNum):
         open("./img/"+str(i)+".jpg","wb")
        
if __name__ == "__main__":
    start = time.time()
    pool = threadpool.ThreadPool(10) #启动10个线程
    requests = threadpool.makeRequests(func,range(10))
    [pool.putRequest(req) for req in requests]
    pool.wait()
    end = time.time()
    print(end-start)

图片-1659065529189

from concurrent.futures import ThreadPoolExecutor
import time

def create(num):
    num = num*100
    endNum =num+100
    for i in range(num,endNum):
         open("./img/"+str(i)+".jpg","wb")
       
        
if __name__ == "__main__":
    start = time.time()
    pool = ThreadPoolExecutor(max_workers=10)
    
    for i in range(10):
        pool.submit(create,(i))
    pool.shutdown()
    end = time.time()
    print(end-start)

图片-1659067232304

多线程看起来也就稍微快一点点。这是因为python的GIL锁缘故,导致多线程同一时刻只能有一个线程运行,也就是线程不是并行的。但是为什么会快一点点,因为io等待的时候会释放GPL锁,切换到其它线程,加上创建文件io需要等待时间不是很长,线程切换也需要时间,前后抵消,提速并不是很明显。如有其它逻辑,有时候多线程反而更慢。

那么什么时候用适合多线程呢?

  • cpu密集型----多线程速度比进程、单线程慢,当然能够用多进程会更好(资源换时间)
  • io密集型----多线程比单线程快,前提条件io等待时间大于线程切换时间。如上例子io等待时间太短(其中创建每张图片io等待估计也就0.002秒),几乎没看出多线程的优势,如换成网络io就会很明显

Comment