09-性能
[toc]
4.5 性能
为了进一步了解增加线程和进程的数量会如何影响下载时间,我们对爬取500个网页时的结果进行了对比,如表4.1所示。
| 脚本 | 线程数 | 进程数 | 时间 | 相对串行的时间比 | 是否出现错误? | | :----- | :----- | :----- | :----- | :----- | :----- | :----- | :----- | | 串行 | 1 | 1 | 1349.798s | 1 | 否 | | 多线程 | 5 | 1 | 361.504s | 3.73 | 否 | | 多线程 | 10 | 1 | 275.492s | 4.9 | 否 | | 多线程 | 20 | 1 | 298.168s | 4.53 | 是 | | 多进程 | 2 | 2 | 726.899s | 1.86 | 否 | | 多进程 | 2 | 4 | 559.93s | 2.41 | 否 | | 多进程 | 2 | 8 | 451.772s | 2.99 | 是 | | 多进程 | 5 | 2 | 383.438s | 3.52 | 否 | | 多进程 | 5 | 4 | 156.389s | 8.63 | 是 | | 多进程 | 5 | 8 | 296.610s | 4.55 | 是 |
表格的第5列给出的是相对于串行下载的时间比。可以看出,性能的增长与线程和进程的数量并不是成线性比例的,而是趋于对数,也就是说添加过多线程后反而会降低性能。比如,使用1个进程5个线程时,性能大约为串行时的4倍,使用10个线程时性能只达到了串行下载时的5倍,而使用20个线程时实际上还降低了性能。
根据系统的不同,性能的增加和损失可能会有所不同;不过,众所周知的是每个额外的线程都有助于加速执行,但其效果低于之前添加的线程(也就是说这不是一个线性加速的过程)。这是可以预见到的现象,因为此时进程需要在更多线程之间进行切换,专门用于每一个线程的时间就会变少。
此外,下载的带宽是有限的,因此最终添加新线程将无法带来更快的下载速度。当你自己运行该代码时,可能会注意到错误(比如 urlopen error [Errno 101] Network is unreachable )会贯穿整个测试过程,尤其是当你使用大量线程或进程时。这显示不是理想状态,你会比选择更少的线程数时遇到更频繁的下载错误。当然,如果你在分布式或云服务器环境中运行它,网络限制则会有所不同。表4.1最后一列跟踪了我在测试时遇到的错误情况,我所使用的环境是普通运营商网络连接的单台笔记本电脑。
你得到的结果可能会不同,而且该表是根据笔记本电脑而不是服务器(带宽更好、后台进程更少)来创建的,因此我要求你为自己的计算机和/或服务器创建一个类似的表格。一旦你发现了自己机器的极限,又想获得更好的性能,就需要在多台服务器上分布式部署爬虫,并且所有服务器都要指向同一个Redis队列实例。