多线程与协程爬虫有很大区别吗?多线程转协程能优化多少?

2020-08-06 15:38:56 +08:00
 Te11UA
目前一个爬虫项目运行在 4c8g 下的机器,requests 运行在 4 进程* 400 线程下,单页面 200k 左右。
最近发现 CPU 和内存都有一点瓶颈,如果转成协程的话是否能优化爬取速率呢?
(不讨论反爬的情况,单纯从爬虫效率上看)
7624 次点击
所在节点    Python
54 条回复
xiaolinjia
2020-08-06 15:47:32 +08:00
理论上协程少了线程之间的切换,速度和内存应该会更优点。
araraloren
2020-08-06 15:53:22 +08:00
协程的东西都运行在一个线程,python 的话应该有不少优势,毕竟 python 有 GIL
Vegetable
2020-08-06 16:12:12 +08:00
协程理论上是更好的方案,但是效率上是否能提高存疑。
你这已经有 1600 线程了,单页面 200k 就是 200k*1600 同时下载,超过 300mb 的流量,带宽不会成为瓶颈吗
locoz
2020-08-06 16:17:53 +08:00
对于爬虫而言,从多线程换成协程在性能方面提升很小,甚至如果你操作流程中有同步的东西的话还会降低性能。但用协程来做之后,内存占用方面会有明显下降,也就是说你可能能开更高的并发,相对而言也会有一定的采集速率提升。
youxiachai
2020-08-06 16:20:45 +08:00
@locoz ls 有个大佬做了一个算术题, 相比更高的并发...带宽才是瓶颈吧..
wysnylc
2020-08-06 16:30:19 +08:00
协程是跑在一个线程里,多线程转成协程除了内存占用下降性能也会下降
协程就不是这么用的别无脑协程
locoz
2020-08-06 16:38:45 +08:00
@youxiachai #5 带宽是可以随便加的,而且也不会有真正意义上的同时下载(毕竟服务器返回的时间并不相同),所以其实带宽并不是什么大问题...
locoz
2020-08-06 16:40:52 +08:00
@wysnylc #6 你忘了 GIL
Te11UA
2020-08-06 17:13:50 +08:00
@Vegetable 带宽实际上没有那么多,因为代理质量一般,而且有一定的解析操作。用的是按量付费,看监控就十几 MB 而已。
tigerstudent
2020-08-06 17:14:59 +08:00
gevent 使用很简单,可以直接试试
Te11UA
2020-08-06 17:15:15 +08:00
@locoz 了解,我去尝试先,目前内存的确是有点瓶颈
newmlp
2020-08-06 17:30:55 +08:00
别骗自己了,就线程和协程那点性能差异你用一行垃圾代码就搞没了,还是花时间优化下自己的业务代码吧
hakono
2020-08-06 17:50:33 +08:00
400 个线程,你 cpu 不瓶颈就怪了。。。。。
现代的程序一般是一个线程对应 cpu 的一个核心性能才比较好,开 400 个线程和以前单核 cou 跑多线程一样性能没什么提升反倒降低性能

这个情况用协程应该能改善楼主的 cpu 和内存使用情况,而且协程可以实现比多线程更高的并发(协程可以一次轻松发出几千几万个请求,你用线程难道开几千个几万个线程么)
当然你网络带宽死的话,协程也只是比线程更省资源罢了
wysnylc
2020-08-06 17:53:50 +08:00
@newmlp #12 "协程可以一次轻松发出几千几万个请求,你用线程难道开几千个几万个线程么"
看的我尬的不行
xcstream
2020-08-06 17:54:04 +08:00
没多大用 又不是服务器
itskingname
2020-08-06 18:22:22 +08:00
之前爬斗鱼直播弹幕,第一版爬虫用的多线程,5 台服务器最多能同时监控 250 个房间的弹幕。后来使用 asyncio 重构成异步爬虫,只用 3 台机器,可以同时监控 25000 个房间。
zengxs
2020-08-06 18:31:10 +08:00
曾经和小伙伴讨论过这个问题

异步编程要考虑不能引入同步的代码,而 Python 的生态目前来讲,大部分库仍然是同步的,因此强行上异步,会造成开发效率的下降,而性能却不见得能比用多线程快很多

我们最后得出的结论是,除非有一个场景,特别适合使用 asyncio,否则一般还是倾向于使用多线程
zengxs
2020-08-06 18:37:37 +08:00
看了一下楼主的描述,4 核却开了 400 线程,cpu 做线程调度的开销都很大了吧

不考虑反爬单纯考虑性能的话,我觉得可以考虑换成协程
supermoonie
2020-08-06 18:42:54 +08:00
还不如异步 io
saberlong
2020-08-06 19:01:50 +08:00
@wysnylc 现在一般普通主流计算机,直接开几万协程确实没问题。以前开发写测试时,不小心开了几十万协程,还能跑。但是线程却不行,资源占用和上下文切换决定了它不可能开启同样多的数量时还能保证可用。
你的怀疑点应该是一次性发出这么多请求。这得看理解了,如果指发出第一个数据包开始,确实可能。
假设极端情况,被访问的服务器响应很慢,导致发出数据包请求后就在 io 等待。那么协程确实能做到同时有几万个请求在等待响应。只是线程要做到同样量级,需要机器资源就更多了。
不过实际上并没有优势,现实中不会这么极端,瓶颈通常也不在这。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/696184

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX