python的各种网络请求库 urllib3 requests aiohttp 分别请求http和https 的效率对比,多线程、gevent、asyncio对比,超大线程池、2n + 1 线程池对比
此文三个目的,不能光意淫概念误入歧途,有的人以为得概念一套一套的,其实并不是想的那样,实践对比才能出真知,要尊重实践。
此文使用各种网络请求库和各种并发模式和各种大小的线程池来测试请求50000次一个内容源码很小的百度静态页面,分别测试http和https
https://www.baidu.com/content-search.xml
http://www.baidu.com/content-search.xml
网页内容很小,(基本可以排除认为请求得慢,耍赖说是网速带宽差造成的)。
1.总结一下python的各种网络请求库的性能,包括urllib3 和requests和aiohttp
2.总结一下 多线程 asyncio gevent的 并发效率
3.4核cpu情况下对比200线程池并发数量和 9线程池(2 * 4 +1)并发效率。
测试截图如下,nb_log把print时间自动打印出来,方便控制台搜索每秒运行多少次,一定要import nb_log。
测试方案1:
urllib3 + ThreadPoolExecutor 200线程池 +请求连接池 + 请求 https
平均每秒请求完成 750次。
测试方案2
requests + ThreadPoolExecutor 200线程池 +请求连接池 + 请求 https
平均每秒请求完成310次。
测试方案3
urllib3 + gevent 200并发 + 连接池 + 请求https
平均每秒秒请求完成270次。
测试方案4
urllib3 + 线程池 200并发 + 连接池 + 请求http (注意是http,不是https,https会执行更多的代码路径消耗更高的cpu)
平均每秒秒请求完成1300次。
测试方案5
requests + 线程池 200并发 + 连接池 + 请求http (注意是http,不是https)
平均每秒秒请求完成330次。
测试方案6
urllib3 + gevent 200并发 + 连接池 + 请求http (注意是http,不是https)
平均每秒秒请求完成580次。
测试方案7
urllib3 + 线程池 200并发 + 不使用请求连接池 + 请求https (注意是https,不是http)
平均每秒秒请求完成580次。
测试方案8
requests + 线程池 200并发 + 不使用请求连接池 + 请求https (注意是https,不是http)
平均每秒秒请求完成120次。
测试方案9
aiohttp + asyncio 200并发 + 使用请求连接池 + 请求https (注意是https,不是http)
平均每秒秒请求完成990次。
测试方案10
aiohttp + asyncio 200并发 + 使用请求连接池 + 请求http (注意是http,不是https)
平均每秒秒请求完成1080次。
测试方案11
aiohttp + asyncio 200并发 + 不使用请求连接池 + 请求http (注意不使用连接池)
平均每秒秒请求完成400次。
测试方案12
aiohttp + asyncio 200并发 + 不使用请求连接池 + 请求https (注意不使用连接池)
平均每秒秒请求完成170次。
综上所述, 请求http比https快很多
连接池比不使用连接池快很多。
gevent 比线程池慢。
urllib3 比requests快很多。
asyncio + aiohttp 比线程池 + urllib3 效率差不多,绝对不会出现asyncio吊打多线程几十倍,无需过于理论上担忧线程切换消耗大量资源,这只是个理论,实际真实场景下不会强很多,而且同步编程简单很多。
具体原因是每种场景运行次数差别,是因为消耗的cpu单核达到100%了,单核单进程无法再提高速度了,除非是花10万定制一个10ghz主频的cpu液氮散热。
requests包get请求http的url,实际执行的代码是24000行,urllib3包get 请求http的url实际执行11000行代码,因为urllib3实际运行的代码行数只有requests包的一半以下,所以urllib3性能明显好于requests。
具体怎么知道一个函数运行的背后实际执行多少行代码呢,使用pycharm打断点 一行一行慢慢运行慢慢数是可以的,但这样会数到你怀疑人生,使用pip install pysnooper_click_able,然后把装饰器加在需要 分析的 函数就可以统计出来代码运行轨迹和实际执行的总行数。pysnooper_click_able 是神级别黑科技装饰器。
来计算一下执行的 代码实际行数,一次urllib3.get 需要运行1万2000行代码 ,每秒运行了1000次请求,那就是相当于每秒运行了 1千万 行python代码,所以讷还可以了。那些对性能一无所知的小白以为单进程可以每秒请求100万次 url,完完全全的错误了1000倍,因为是没有 使用 pysnooper_click_able 分析代码执行行数,以为发一个url请求只需要执行10几行python代码,大错特错。如果有人认为单进程能每秒请求1万次url,不管你用什么异步并发还是线程并发实现的,我们赌1万人民币可以。
在4核机器上亲求一个非常快的接口,4线程和200线程相比,200线程快很多。如果接口响应耗时长,例如需要耗时1秒,200线程请求完成5万次的时间远远远远小于4线程请求耗时,无需过滤线程多了切换耗资源。
所以大胆点,只要不是纯计算的,有io超过0.5秒的开200个线程,大胆点,不要怕cpu爆炸了,有的买了mac笔记本的人真的害怕开很多线程总是担心线程开多了,笔记本会爆炸会损害,不用担心,炸了我陪你一个。
再说这么爱惜笔记本这么小气的人,为什么非要花1万3买苹果笔记本讷,5800u 8核16线程 + 32g + depping20 系统的笔记本才4000多元不行吗,跑代码的性能开16进程 + 每个进程内部开200个线程,跑起代码来,运行速度远远的暴击不敢开多线程怕mac笔记本爆炸的人。