• Python 简单并发的代码记录


    简单介绍

    近期想优化一下API的请求,顺带测试一下并发编程能快多少,用到进程、线程,顺带保留一些直接可用的简单的并发代码,方便后期复制粘贴

    1、urllib3 网络请求
    2、获取函数执行时间(大致的)
    3、进程的简单实现
    4、线程的简单实现
    5、通过CPU计算以及网络IO请求,简单的对比性能上的差异

    公共代码

    from datetime import datetime
    import urllib3
    import json
    
    manager  = urllib3.PoolManager(num_pools=5)
    
    
    def request_api(site):
        # print(site)
        test_url = 'http://127.0.0.1:9000/'
        r = manager.request('GET', test_url)
        data = r.data
        # json.loads(data)
        return data
    
    def cpu_test(number):
        result = 235 * number
        return result
    
    def print_time(func1, func2):
        start_time = datetime.now()
        func1(func2)
        end_time = datetime.now()
        print(func1, end_time-start_time)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    线程测试 适合 IO密集型:读写

    from concurrent.futures import ThreadPoolExecutor
    
    def thread_map_test(func):
        result = []
        site_list = range(1000)
        with ThreadPoolExecutor(max_workers=12) as executor:
            # 返回结果是一个迭代器
            ans = executor.map(func, site_list)
            for res in ans:
                result.append(res)
        return result
    
    def thread_test(func):
        result = []
        site_list = range(1000)
        with ThreadPoolExecutor(max_workers=5) as executor:
                ans = [executor.submit(func, i) for i in site_list ]
                # as_completed(ans)
                for res in ans:
                    result.append(res.result())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    进程测试 适合CPU密集型:计算

    import multiprocessing
    
    def process_by_map(func):
        data_list = range(1000)
        with multiprocessing.Pool(processes=4) as pool: 
            result = pool.map(func, data_list)
        return result 
    
    # 会阻塞
    def process_by_apply(func):
        result = []
        data_list = range(1000)
        with multiprocessing.Pool(processes=4) as pool: 
            for line in data_list:
                result.append(pool.apply(func, (line,)))
        return result
    
    # 异步非阻塞
    def process_by_apply_async(func):
        result = []
        data_list = range(1000)
        with multiprocessing.Pool(processes=4) as pool: 
            for line in data_list:
                result.append(pool.apply_async(func, (line,)))
        return result
    
    • 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

    综合测试

    注意:多进程必须要写if name == ‘main’: 否则,IDE上面啥也不提示,但是没执行结果,直接点击执行就会提醒有异常

    # 请注意,多进程必须要写if __name__ == '__main__': 
    if __name__ == '__main__':
        
        print('''计算测试 100万次计算''')
        
        # 0:00:00.362031
        print_time(process_by_map, cpu_test)
        # 0:01:48.696417
        print_time(process_by_apply, cpu_test)
        # 0:00:11.481112
        print_time(process_by_apply_async, cpu_test)
        # 0:00:25.352362
        print_time(thread_map_test, cpu_test)
        # 0:00:20.073205
        print_time(thread_test, cpu_test)
        
        print('''网络IO 测试  1000次请求''')
        # 0:00:04.105110
        print_time(process_by_map, request_api)
        # 0:00:07.180077
        print_time(process_by_apply, request_api)
        # 0:00:00.139999
        print_time(process_by_apply_async, request_api)
        # 0:00:02.757811
        print_time(thread_map_test, request_api)
        # 0:00:02.712561
        print_time(thread_test, request_api)
    
    • 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

    结果

    1、网络IO 多线程或者进程的异步请求比较合适
    2、CPU计算 多进程性能差异较大,用map应该是有一定的优化的
    3、CPU 计算 多进程 map 快于 apply_async 快于 apply
    4、网络IO apply_sync 异步 快于 map 快于 apply

    其他

    1、其他还有锁机制,还未测试
    2、对于进程和线程的适用原因,不够清晰,进程上下文切换资源消耗较多,需要找时间了解一下
    3、测试方式和写法还不太合理,记得起再优化吧
    4、对于并发数,需要自行调整,具体如何科学的得到最优解,暂时也还没有研究,只是简单调试了一下

  • 相关阅读:
    C# json序列化实体时,时间戳转Datetime
    台式电脑的IP地址在哪里?解密台式电脑网络连接的秘密!
    【数据结构】算法的时间复杂度和空间复杂度
    redis之集群
    vue 点击事件失效检查办法
    PHP require、include、require_once 和 include_once 的区别
    上位机图像处理和嵌入式模块部署(树莓派4b的一种固件部署方法)
    Matlab中saveobj函数的使用
    简易Tomcat服务器
    RabbitMQ系列【15】AmqpAdmin使用详解
  • 原文地址:https://blog.csdn.net/weixin_43839586/article/details/133951245