• 【python】多线程、多进程性能比较


    测试样例:复制3部电影,每部大小为2.04G,比较复制耗时

    1.单进程单线程

    import os
    import threading
    import datetime
    
    t0 = datetime.datetime.now()
    
    source_dir = "F:\多线程测试\origin"
    dest_dir = "F:\多线程测试\copy"
    
    # 3.读取源文件夹的文件列表
    file_list = os.listdir(source_dir)
    
    # 4.遍历文件列表实现拷贝
    for file_name in file_list:
    
        print(file_name, "--拷贝的进程pid是:", os.getpid())
        print(file_name, "--拷贝的线程是:", threading.current_thread())
        # 1.拼接源文件路径和目标文件所在的路径
        source_path = source_dir + "/" + file_name
        dest_path = dest_dir + "/" + file_name
    
    # 2.打开源文件和目标文件
        with open(source_path, "rb") as source_file:
            with open(dest_path, "wb") as dest_file:
                # 3.循环读取源文件到目标路径
                while True:
                    data = source_file.read(1024)
                    if data:
                        dest_file.write(data)
                    else:
                        break
    
    print(datetime.datetime.now()-t0)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    1_同学麦娜丝.mkv --拷贝的进程pid是: 18016
    1_同学麦娜丝.mkv --拷贝的线程是: <_MainThread(MainThread, started 308)>
    2_同学麦娜丝.mkv --拷贝的进程pid是: 18016
    2_同学麦娜丝.mkv --拷贝的线程是: <_MainThread(MainThread, started 308)>
    3_同学麦娜丝.mkv --拷贝的进程pid是: 18016
    3_同学麦娜丝.mkv --拷贝的线程是: <_MainThread(MainThread, started 308)>
    0:03:21.734185

    2.多线程

    import threading
    import os
    import datetime
    
    def copy_file(file_name, source_dir, dest_dir):
        print(file_name, "--拷贝的进程pid是:", os.getpid())
        print(file_name, "--拷贝的线程是:", threading.current_thread())
        # 1.拼接源文件路径和目标文件所在的路径
        source_path = source_dir + "/" + file_name
        dest_path = dest_dir + "/" + file_name
        # 2.打开源文件和目标文件
        with open(source_path, "rb") as source_file:
            with open(dest_path, "wb") as dest_file:
                # 3.循环读取源文件到目标路径
                while True:
                    data = source_file.read(1024)
                    if data:
                        dest_file.write(data)
                    else:
                        break
    
    
    if __name__ == '__main__':
        t0 = datetime.datetime.now()
    
        # 1.定义源文件夹和目标文件夹
        source_dir = "F:\多线程测试\origin"
        dest_dir = "F:\多线程测试\copy"
    
        # 2.创建目标文件夹
        try:
            os.mkdir(dest_dir)
        except:
            print("目标文件夹已经存在!")
    
        # 3.读取源文件夹的文件列表
        file_list = os.listdir(source_dir)
    
        # 4.遍历文件列表实现拷贝
        for file_name in file_list:
            # copy_file(file_name, source_dir, dest_dir)
            # 5.使用多线程实现多任务拷贝
            sub_thread = threading.Thread(target=copy_file,
                                          args=(file_name, source_dir, dest_dir))
            sub_thread.start()
            sub_thread.join()
            print(datetime.datetime.now()-t0)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    1_同学麦娜丝.mkv --拷贝的进程pid是: 17212
    1_同学麦娜丝.mkv --拷贝的线程是:
    0:01:05.723885
    2_同学麦娜丝.mkv --拷贝的进程pid是: 17212
    2_同学麦娜丝.mkv --拷贝的线程是:
    0:02:11.567183
    3_同学麦娜丝.mkv --拷贝的进程pid是: 17212
    3_同学麦娜丝.mkv --拷贝的线程是:
    0:03:20.944711

    3.多进程

    import multiprocessing
    import os
    import datetime
    
    
    def copy_file(file_name, source_dir, dest_dir):
        print(file_name, "--拷贝的进程pid是:", os.getpid())
        # 1.拼接源文件路径和目标文件所在的路径
        source_path = source_dir + "/" + file_name
        dest_path = dest_dir + "/" + file_name
        # 2.打开源文件和目标文件
        with open(source_path, "rb") as source_file:
            with open(dest_path, "wb") as dest_file:
                # 3.循环读取源文件到目标路径
                while True:
                    data = source_file.read(1024)
                    if data:
                        dest_file.write(data)
                    else:
                        break
    
    
    if __name__ == '__main__':
    
        t0 = datetime.datetime.now()
    
        # 1.定义源文件夹和目标文件夹
        source_dir = "F:\多线程测试\origin"
        dest_dir = "F:\多线程测试\copy"
    
        # 2.创建目标文件夹
        try:
            os.mkdir(dest_dir)
        except:
            print("目标文件夹已经存在!")
    
        # 3.读取源文件夹的文件列表
        file_list = os.listdir(source_dir)
    
        # 4.遍历文件列表实现拷贝
        for file_name in file_list:
            # copy_file(file_name, source_dir, dest_dir)
            # 5.使用多进程实现多任务拷贝
            sub_process = multiprocessing.Process(target=copy_file,
                                                  args=(file_name, source_dir, dest_dir))
            sub_process.start()
            sub_process.join()
            print(datetime.datetime.now() - t0)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    1_同学麦娜丝.mkv --拷贝的进程pid是: 17280
    0:01:30.373696
    2_同学麦娜丝.mkv --拷贝的进程pid是: 21340
    0:02:51.638254
    3_同学麦娜丝.mkv --拷贝的进程pid是: 14360
    0:04:03.929954

    比较:

    方式耗时
    单进程单线程0:03:21
    单进程多线程0:03:20
    多进程0:04:03

    在这个测试样例中,多进程最为耗时,可能的原因是多进程上下文切换更为耗时,同时本场景不属于CPU密集场景,并不适合多进程;单进程多线程和单进程单线程的耗时差不多,是我没想到的,感觉没有发挥出多线程的优势来,原因可能是本场景不涉及到CPU计算,纯IO密集,能提高的空间有限?也可能是复制的电影数量少了?
    我尝试将复制的电影数量提高到6个,观察两种方式的耗时变化

    方式耗时
    单进程单线程0:07:37
    单进程多线程0:07:40

    好像不符合期望

    代码参考:https://blog.csdn.net/weixin_44917390/article/details/119610760?spm=1001.2014.3001.5506(很不错)

    ————————————————————
    2022.10.30.更新:
    Python的多线程不是真正的多线程,因为GIL的原因,同一时间只能有一个线程在执行,哪怕时多核,换句话说,就算是十核的CPU执行多线程,也只能用到一个核,此时就是单核多线程。对比JAVA,多个线程能分发在多个核上同时运行(线程数≤核数)。
    Python要想利用多核怎么办呢?
    方法一:多进程。
    方法二:将计算密集型任务用C语言来写,然后用Python来调用。
    多说一句:C语言这类“很快”的语言最适合的就是计算密集型任务,在I/O密集任务上相比Python并没有绝对的优势。

    那么Python的多线程还有用武之地吗?
    在爬虫,web应用等I/O密集场景,还是有效果的。因为多线程的本质是避免CPU闲置浪费,此时就算单核多线程也能充分利用它的性能。

    参考:
    https://www.zhihu.com/question/23474039/answer/269526476?utm_source=wechatMessage_answer_bottom

  • 相关阅读:
    【CSS】画个三角形或圆形或环
    第二讲 IMU传感器
    Ubuntu18.04开机自动启动终端并运行脚本
    数学建模笔记
    2022-08-04 clickhouse的select子句
    我在高职教STM32——GPIO入门之按键输入(1)
    maven
    资产连接支持会话分屏,新增Passkey用户认证方式,支持查看在线用户信息,JumpServer堡垒机v3.7.0发布
    测试环境搭建教程(APP+WEB)
    Mybatis 查询数据库
  • 原文地址:https://blog.csdn.net/xiangxiang613/article/details/127598354