You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Yao b6657bd39e
feat: 添加对爬虫类Spider的优化,包括引入psutil库来监控CPU和内存使用情况,以及使用tracemalloc库来追踪内存使用。同时,删除了冗余的代码和注释,使代码更加简洁。
2 months ago
..
000 普通做法.py feat: 添加对爬虫类Spider的优化,包括引入psutil库来监控CPU和内存使用情况,以及使用tracemalloc库来追踪内存使用。同时,删除了冗余的代码和注释,使代码更加简洁。 2 months ago
010 多进程.py feat: 添加对爬虫类Spider的优化,包括引入psutil库来监控CPU和内存使用情况,以及使用tracemalloc库来追踪内存使用。同时,删除了冗余的代码和注释,使代码更加简洁。 2 months ago
020 多线程.py feat: 添加对爬虫类Spider的优化,包括引入psutil库来监控CPU和内存使用情况,以及使用tracemalloc库来追踪内存使用。同时,删除了冗余的代码和注释,使代码更加简洁。 2 months ago
030 协程.py feat: 添加对爬虫类Spider的优化,包括引入psutil库来监控CPU和内存使用情况,以及使用tracemalloc库来追踪内存使用。同时,删除了冗余的代码和注释,使代码更加简洁。 2 months ago
040 异步.py feat: 添加对爬虫类Spider的优化,包括引入psutil库来监控CPU和内存使用情况,以及使用tracemalloc库来追踪内存使用。同时,删除了冗余的代码和注释,使代码更加简洁。 2 months ago
os 机制.md feat: 添加对爬虫类Spider的优化,包括引入psutil库来监控CPU和内存使用情况,以及使用tracemalloc库来追踪内存使用。同时,删除了冗余的代码和注释,使代码更加简洁。 2 months ago
readme.md feat: 添加对爬虫类Spider的优化,包括引入psutil库来监控CPU和内存使用情况,以及使用tracemalloc库来追踪内存使用。同时,删除了冗余的代码和注释,使代码更加简洁。 2 months ago
util.py feat: 添加对爬虫类Spider的优化,包括引入psutil库来监控CPU和内存使用情况,以及使用tracemalloc库来追踪内存使用。同时,删除了冗余的代码和注释,使代码更加简洁。 2 months ago
概念.md feat: 添加对爬虫类Spider的优化,包括引入psutil库来监控CPU和内存使用情况,以及使用tracemalloc库来追踪内存使用。同时,删除了冗余的代码和注释,使代码更加简洁。 2 months ago
进程、线程、协程.md feat: 添加对爬虫类Spider的优化,包括引入psutil库来监控CPU和内存使用情况,以及使用tracemalloc库来追踪内存使用。同时,删除了冗余的代码和注释,使代码更加简洁。 2 months ago

readme.md

目标

本节使用一个爬虫任务和计算任务来展示如何追求代码的性能 。 充分理解线程、协程、进程、同步、异步、阻塞、非阻塞等概念,并能够根据具体场景选择合适的并发模型。 主线问题如何解决IO和计算速度不匹配、如何任务分解、分发和协作 。

任务

1、CPU密集型/计算密集型:

  将sum(i * i for i in range(10**8))作为一个子任务运行5次分别使用单线程、多线程、多进程、多协程、异步等方式并对比运行时间、内存使用、CPU使用等指标。

2、IO密集型

讨论分析

1、CPU密集型/计算密集型:

为控制变量代码在同一台设备上运行且关闭其他进程保证CPU资源不被其他进程占用。测试结果如下

普通做法:

运行前:

CPU使用率0.0%内存使用率53.3%

运行后:

CPU使用率0.6%内存使用率53.0%内存使用0.003336MB峰值内存使用0.004216MB单个子任务运行平均时间7.86s总运行时间39.31s

运行结束30秒后

CPU使用率0.6%内存使用率53.0%

多进程:

运行前:

CPU使用率0.0%内存使用率52.8%

运行后:

CPU使用率1.3%内存使用率52.9%内存使用0.096089MB峰值内存使用0.121865MB单个子任务运行平均时间0.654s总运行时间1.86s

运行结束30秒后

CPU使用率0.6%内存使用率52.7%

多线程:

运行前:

CPU使用率3.8%内存使用率53.1%

运行后:

CPU使用率3.6%内存使用率53.1%内存使用0.001472MB峰值内存使用0.019296MB单个子任务运行平均时间38.89s总运行时间39.77s

运行结束30秒后

CPU使用率0.7%内存使用率52.9%

多线程 + 线程池:

运行前:

CPU使用率0.0%内存使用率52.9%

运行后:

CPU使用率0.7%内存使用率53.1%内存使用0.000952MB峰值内存使用0.036604MB单个子任务运行平均时间40.49s总运行时间41.16s

运行结束30秒后

CPU使用率0.6%内存使用率52.9%

多协程:

运行前:

CPU使用率1.1%内存使用率53.4%

运行后:

CPU使用率0.2%内存使用率53.4%内存使用0.009448MB峰值内存使用0.011027MB单个子任务运行平均时间9.14s总运行时间45.70s

运行结束30秒后

CPU使用率0.6%内存使用率53.4%

多进程 + 异步:

运行前:

CPU使用率0.8%内存使用率54.9%

运行后:

CPU使用率0.6%内存使用率54.9%内存使用0.123481MB峰值内存使用0.188774MB单个子任务运行平均时间0.63s总运行时间1.85s

运行结束30秒后

CPU使用率0.9%内存使用率55.0%

2、IO密集型

  为控制变量,代码在同一台设备上运行,关闭其他进程,并在相同的网络环境下运行,保证网络资源不被其他进程占用。

普通做法:

运行前:

CPU使用率0.0%内存使用率52.5%

运行后:

CPU使用率0.9%内存使用率52.6%内存使用0.074968MB峰值内存使用4.162339MB总运行时间5.56s

运行结束30秒后

CPU使用率0.6%内存使用率52.5%

多进程:

运行前:

CPU使用率0.0%内存使用率52.7%

运行后:

CPU使用率5.0%内存使用率52.8%内存使用0.03219MB峰值内存使用0.085236MB总运行时间5.81s

运行结束30秒后

CPU使用率1.2%内存使用率53.1%

多线程:

运行前:

CPU使用率0.0%内存使用率52.9%

运行后:

CPU使用率0.1%内存使用率53.0%内存使用MB峰值内存使用MB总运行时间1.63s

运行结束30秒后

CPU使用率0.5%内存使用率52.9%

多线程 + 线程池:

运行前:

CPU使用率1.3%内存使用率53.2%

运行后:

CPU使用率1.3%内存使用率53.1%内存使用0.092493MB峰值内存使用4.371028MB总运行时间1.47s

运行结束30秒后

CPU使用率0.8%内存使用率53.2%

多协程:

运行前:

CPU使用率1.1%内存使用率54.4%

运行后:

CPU使用率0.8%内存使用率54.4%内存使用0.753684MB峰值内存使用15.09151MB总运行时间1.45s

运行结束30秒后

CPU使用率0.8%内存使用率54.4%

多进程 + 异步:

运行前:

CPU使用率1.5%内存使用率60.0%

运行后:

CPU使用率0.8%内存使用率59.8%内存使用0.569592MB峰值内存使用6.360097MB总运行时间7.40s

运行结束30秒后

CPU使用率1.3%内存使用率59.6%

总结

1、CPU密集型/计算密集型:

普通做法 多进程 多线程 多线程+线程池 多协程 多进程+异步
运行前CPU使用率 0.0% 0.0% 3.8% 0.0% 1.1% 0.8%
运行后CPU使用率 0.6% 1.3% 3.6% 0.7% 0.2% 0.6%
运行结束30秒后CPU使用率 0.6% 0.6% 0.7% 0.6% 0.6% 0.9%
运行前内存使用率 53.3% 52.8% 53.1% 52.9% 53.4% 54.9%
运行后内存使用率 53.0% 52.9% 53.1% 53.1% 53.4% 54.9%
运行结束30秒后内存使用率 53.0% 52.7% 52.9% 52.9% 53.4% 55.0%
内存使用 0.003336MB 0.096089MB 0.001472MB 0.000952MB 0.009448MB 0.123481MB
峰值内存使用 0.004216MB 0.121865MB 0.019296MB 0.036604MB 0.011027MB 0.188774MB
单个子任务运行平均时间 7.86s 0.654s 38.89s 40.49s 9.14s 0.63s
总运行时间 39.31s 1.86s 39.77s 41.16s 45.70s 1.85s

  根据表格中的数据,我们可以对不同的并发和并行编程方法进行详细的总结:

普通做法

  • CPU使用率在任务运行前、运行后和运行结束30秒后的CPU使用率都较低表明普通做法没有充分利用CPU资源。
  • 内存使用率:内存使用率变化不大,表明普通做法对内存的影响较小。
  • 内存使用:内存使用量和峰值内存使用量都很低。
  • 运行时间:单个子任务和总任务的运行时间都较长,表明普通做法效率较低。

多进程

  • CPU使用率在任务运行后CPU使用率显著增加表明多进程方法能够充分利用多核CPU的优势。
  • 内存使用率:内存使用率略有增加,但变化不大。
  • 内存使用:内存使用量和峰值内存使用量较高,表明多进程方法对内存的需求较大。
  • 运行时间单个子任务和总任务的运行时间都显著减少表明多进程方法在处理CPU密集型任务时效率最高。

多线程

  • CPU使用率在任务运行前、运行后和运行结束30秒后的CPU使用率都较低表明多线程方法没有充分利用CPU资源。
  • 内存使用率:内存使用率变化不大。
  • 内存使用:内存使用量和峰值内存使用量较低。
  • 运行时间单个子任务和总任务的运行时间都较长表明多线程方法在处理CPU密集型任务时效率较低。

多线程+线程池

  • CPU使用率在任务运行后CPU使用率略有增加但变化不大。
  • 内存使用率:内存使用率变化不大。
  • 内存使用:内存使用量和峰值内存使用量较低。
  • 运行时间:单个子任务和总任务的运行时间都较长,表明多线程+线程池方法在处理CPU密集型任务时效率较低。

多协程

  • CPU使用率在任务运行前、运行后和运行结束30秒后的CPU使用率都较低表明多协程方法没有充分利用CPU资源。
  • 内存使用率:内存使用率变化不大。
  • 内存使用:内存使用量和峰值内存使用量较低。
  • 运行时间单个子任务和总任务的运行时间都较长表明多协程方法在处理CPU密集型任务时效率较低。

多进程+异步

  • CPU使用率在任务运行后CPU使用率显著增加表明多进程+异步方法能够充分利用多核CPU的优势。
  • 内存使用率:内存使用率略有增加,但变化不大。
  • 内存使用:内存使用量和峰值内存使用量较高,表明多进程+异步方法对内存的需求较大。
  • 运行时间:单个子任务和总任务的运行时间都显著减少,表明多进程+异步方法在处理CPU密集型任务时效率最高。

结论

  • 多进程多进程+异步方法在处理CPU密集型任务时效率最高能够充分利用多核CPU的优势但对内存的需求较大。
  • 多线程多线程+线程池方法在处理CPU密集型任务时效率较低主要是由于Python的全局解释器锁GIL的存在无法实现真正的并行。
  • 多协程方法在处理CPU密集型任务时效率较低但在处理I/O密集型任务时可能会有更好的表现。
  • 普通做法效率最低,无法充分利用系统资源。

2、IO密集型

普通做法 多进程 多线程 多线程+线程池 多协程 多进程+异步
运行前CPU使用率 0.0% 0.0% 0.0% 1.3% 1.1% 1.5%
运行后CPU使用率 0.9% 5.0% 0.1% 1.3% 0.8% 0.8%
运行结束30秒后CPU使用率 0.6% 1.2% 0.5% 0.8% 0.8% 1.3%
运行前内存使用率 52.5% 52.7% 52.9% 53.2% 54.4% 60.0%
运行后内存使用率 52.6% 52.8% 53.0% 53.1% 54.4% 59.8%
运行结束30秒后内存使用率 52.5% 53.1% 52.9% 53.2% 54.4% 59.6%
内存使用 0.074968MB 0.03219MB N/A 0.092493MB 0.753684MB 0.569592MB
峰值内存使用 4.162339MB 0.085236MB N/A 4.371028MB 15.09151MB 6.360097MB
总运行时间 5.56s 5.81s 1.63s 1.47s 1.45s 7.40s

  根据表格中的数据,我们可以对不同的并发和并行编程方法进行详细的总结:

普通做法

  • CPU使用率在任务运行前、运行后和运行结束30秒后的CPU使用率都较低表明普通做法没有充分利用CPU资源。
  • 内存使用率:内存使用率变化不大,表明普通做法对内存的影响较小。
  • 内存使用:内存使用量和峰值内存使用量都很低。
  • 运行时间总运行时间为5.56秒,表明普通做法效率较低。

多进程

  • CPU使用率在任务运行后CPU使用率显著增加表明多进程方法能够充分利用多核CPU的优势。
  • 内存使用率:内存使用率略有增加,但变化不大。
  • 内存使用:内存使用量和峰值内存使用量较低。
  • 运行时间总运行时间为5.81秒略高于普通做法表明多进程方法在处理IO密集型任务时效率较高。

多线程

  • CPU使用率在任务运行前、运行后和运行结束30秒后的CPU使用率都较低表明多线程方法没有充分利用CPU资源。
  • 内存使用率:内存使用率变化不大。
  • 内存使用:内存使用量和峰值内存使用量较低。
  • 运行时间总运行时间为1.63秒显著低于普通做法表明多线程方法在处理IO密集型任务时效率较高。

多线程+线程池

  • CPU使用率在任务运行后CPU使用率略有增加但变化不大。
  • 内存使用率:内存使用率变化不大。
  • 内存使用:内存使用量和峰值内存使用量较低。
  • 运行时间总运行时间为1.47秒,显著低于普通做法,表明多线程+线程池方法在处理IO密集型任务时效率较高。

多协程

  • CPU使用率在任务运行前、运行后和运行结束30秒后的CPU使用率都较低表明多协程方法没有充分利用CPU资源。
  • 内存使用率:内存使用率变化不大。
  • 内存使用:内存使用量和峰值内存使用量较高。
  • 运行时间总运行时间为1.45秒显著低于普通做法表明多协程方法在处理IO密集型任务时效率较高。

多进程+异步

  • CPU使用率在任务运行后CPU使用率显著增加表明多进程+异步方法能够充分利用多核CPU的优势。
  • 内存使用率:内存使用率略有增加,但变化不大。
  • 内存使用:内存使用量和峰值内存使用量较高。
  • 运行时间总运行时间为7.40秒,略高于普通做法,表明多进程+异步方法在处理IO密集型任务时效率较低。

结论

  • 多线程多线程+线程池多协程方法在处理IO密集型任务时效率最高能够显著减少总运行时间。
  • 多进程方法在处理IO密集型任务时效率较高但略低于多线程和多协程方法。
  • 多进程+异步方法在处理IO密集型任务时效率较低总运行时间较长。
  • 普通做法效率最低,无法充分利用系统资源。