目前计算机程序一般会遇到两类I/O:硬盘I/O和网络I/O。我就针对网络I/O的场景分析下python3下进程、线程、协程效率的对比。进程采用multiprocessing.Pool进程池,线程是自己封装的进程池,协程采用gevent的库。用python3自带的urlllib.request和开源的requests做对比。代码如下:

import urllib.request

import requests

import time

import multiprocessing

import threading

import queue

def startTimer():

return time.time()

def ticT(startTime):

useTime = time.time() - startTime

return round(useTime, 3)

#def tic(startTime, name):

# useTime = time.time() - startTime

# print('[%s] use time: %1.3f' % (name, useTime))

def download_urllib(url):

req = urllib.request.Request(url,

headers={'user-agent': 'Mozilla/5.0'})

res = urllib.request.urlopen(req)

data = res.read()

try:

data = data.decode('gbk')

except UnicodeDecodeError:

data = data.decode('utf8', 'ignore')

return res.status, data

def download_requests(url):

req = requests.get(url,

headers={'user-agent': 'Mozilla/5.0'})

return req.status_code, req.text

class threadPoolManager:

def __init__(self,urls, workNum=10000,threadNum=20):

self.workQueue=queue.Queue()

self.threadPool=[]

self.__initWorkQueue(urls)

self.__initThreadPool(threadNum)

def __initWorkQueue(self,urls):

for i in urls:

self.workQueue.put((download_requests,i))

def __initThreadPool(self,threadNum):

for i in range(threadNum):

self.threadPool.append(work(self.workQueue))

def waitAllComplete(self):

for i in self.threadPool:

if i.isAlive():

i.join()

class work(threading.Thread):

def __init__(self,workQueue):

threading.Thread.__init__(self)

self.workQueue=workQueue

self.start()

def run(self):

while True:

if self.workQueue.qsize():

do,args=self.workQueue.get(block=False)

do(args)

self.workQueue.task_done()

else:

break

urls = ['http://www.ustchacker.com'] * 10

urllibL = []

requestsL = []

multiPool = []

threadPool = []

N = 20

PoolNum = 100

for i in range(N):

print('start %d try' % i)

urllibT = startTimer()

jobs = [download_urllib(url) for url in urls]

#for status, data in jobs:

# print(status, data[:10])

#tic(urllibT, 'urllib.request')

urllibL.append(ticT(urllibT))

print('1')

requestsT = startTimer()

jobs = [download_requests(url) for url in urls]

#for status, data in jobs:

# print(status, data[:10])

#tic(requestsT, 'requests')

requestsL.append(ticT(requestsT))

print('2')

requestsT = startTimer()

pool = multiprocessing.Pool(PoolNum)

data = pool.map(download_requests, urls)

pool.close()

pool.join()

multiPool.append(ticT(requestsT))

print('3')

requestsT = startTimer()

pool = threadPoolManager(urls, threadNum=PoolNum)

pool.waitAllComplete()

threadPool.append(ticT(requestsT))

print('4')

import matplotlib.pyplot as plt

x = list(range(1, N+1))

plt.plot(x, urllibL, label='urllib')

plt.plot(x, requestsL, label='requests')

plt.plot(x, multiPool, label='requests MultiPool')

plt.plot(x, threadPool, label='requests threadPool')

plt.xlabel('test number')

plt.ylabel('time(s)')

plt.legend()

plt.show()

运行结果如下:

从上图可以看出,python3自带的urllib.request效率还是不如开源的requests,multiprocessing进程池效率明显提升,但还低于自己封装的线程池,有一部分原因是创建、调度进程的开销比创建线程高(测试程序中我把创建的代价也包括在里面)。

下面是gevent的测试代码:

import urllib.request

import requests

import time

import gevent.pool

import gevent.monkey

gevent.monkey.patch_all()

def startTimer():

return time.time()

def ticT(startTime):

useTime = time.time() - startTime

return round(useTime, 3)

#def tic(startTime, name):

# useTime = time.time() - startTime

# print('[%s] use time: %1.3f' % (name, useTime))

def download_urllib(url):

req = urllib.request.Request(url,

headers={'user-agent': 'Mozilla/5.0'})

res = urllib.request.urlopen(req)

data = res.read()

try:

data = data.decode('gbk')

except UnicodeDecodeError:

data = data.decode('utf8', 'ignore')

return res.status, data

def download_requests(url):

req = requests.get(url,

headers={'user-agent': 'Mozilla/5.0'})

return req.status_code, req.text

urls = ['http://www.ustchacker.com'] * 10

urllibL = []

requestsL = []

reqPool = []

reqSpawn = []

N = 20

PoolNum = 100

for i in range(N):

print('start %d try' % i)

urllibT = startTimer()

jobs = [download_urllib(url) for url in urls]

#for status, data in jobs:

# print(status, data[:10])

#tic(urllibT, 'urllib.request')

urllibL.append(ticT(urllibT))

print('1')

requestsT = startTimer()

jobs = [download_requests(url) for url in urls]

#for status, data in jobs:

# print(status, data[:10])

#tic(requestsT, 'requests')

requestsL.append(ticT(requestsT))

print('2')

requestsT = startTimer()

pool = gevent.pool.Pool(PoolNum)

data = pool.map(download_requests, urls)

#for status, text in data:

# print(status, text[:10])

#tic(requestsT, 'requests with gevent.pool')

reqPool.append(ticT(requestsT))

print('3')

requestsT = startTimer()

jobs = [gevent.spawn(download_requests, url) for url in urls]

gevent.joinall(jobs)

#for i in jobs:

# print(i.value[0], i.value[1][:10])

#tic(requestsT, 'requests with gevent.spawn')

reqSpawn.append(ticT(requestsT))

print('4')

import matplotlib.pyplot as plt

x = list(range(1, N+1))

plt.plot(x, urllibL, label='urllib')

plt.plot(x, requestsL, label='requests')

plt.plot(x, reqPool, label='requests geventPool')

plt.plot(x, reqSpawn, label='requests Spawn')

plt.xlabel('test number')

plt.ylabel('time(s)')

plt.legend()

plt.show()

运行结果如下:

从上图可以看到,对于I/O密集型任务,gevent还是能对性能做很大提升的,由于协程的创建、调度开销都比线程小的多,所以可以看到不论使用gevent的Spawn模式还是Pool模式,性能差距不大。

因为在gevent中需要使用monkey补丁,会提高gevent的性能,但会影响multiprocessing的运行,如果要同时使用,需要如下代码:

gevent.monkey.patch_all(thread=False, socket=False, select=False)

可是这样就不能充分发挥gevent的优势,所以不能把multiprocessing Pool、threading Pool、gevent Pool在一个程序中对比。不过比较两图可以得出结论,线程池和gevent的性能最优的,其次是进程池。附带得出个结论,requests库比urllib.request库性能要好一些哈:-)

python协程池_python3下multiprocessing、threading和gevent性能对比—-暨进程池、线程池和协程池性能对比 | 学步园...相关推荐

  1. 一个小故事讲明白进程、线程、Kotlin 协程到底啥关系?

    前言 协程系列文章: 一个小故事讲明白进程.线程.Kotlin 协程到底啥关系? 少年,你可知 Kotlin 协程最初的样子? 讲真,Kotlin 协程的挂起/恢复没那么神秘(故事篇) 讲真,Kotl ...

  2. python和c运行速度的对比实验_Python中单线程、多线程和多进程的效率对比实验...

    原标题:Python中单线程.多线程和多进程的效率对比实验 文 | 饒木陽 Python是运行在解释器中的语言,查找资料知道,python中有一个全局锁(GIL),在使用多进程(Thread)的情况下 ...

  3. Linux--进程和计划任务管理 理论干货+实操(程序,进程,线程之间关系的详解,静态与动态查看进程方式,控制进程的 方式,一次性任务与周期性任务的设置)

    文章目录 前言 一:程序,进程,线程之间的关系 1.1:进程概述 1.2:应用程序,进程和线程的关系 1.2.1:程序和进程的关系 1.2.2:进程和线程的关系 二:查看进程 2.1:静态查看 ps命 ...

  4. python scapy 抓包_Python3下基于Scapy库完成网卡抓包解析

    Scapy是一个可以让用户发送.侦听和解析并伪装网络报文的Python程序.这些功能可以用于制作侦测.扫描和攻击网络的工具. 在 Python 代码中可以通过 sniff 函数调用抓包分析,并对抓到的 ...

  5. win7 php搭建博客,win7下wordPress本地搭建博客详解(深度亲测整理—傻瓜式详细教程) | 学步园...

    搭建一个wordPress作为一个个人博客本来是特别简单的事情,但是网上的各种转载让初学者举步维艰,我就本身条件而言,会java EE,懂mysql都花费了我好长时间才搭建好本地博客. 注意:这个是本 ...

  6. python pcm 静音_理解和使用alsa配置-默认静音,必须先用amixer解除主音量和pcm音量的静音 | 学步园...

    ALSA声卡驱动程序的配置 对于声卡驱动程序,除了内核自带的驱动程序之外,您还可以使用Advanced Linux Sound Architecture(ALSA,http://www.alsa-pr ...

  7. python多线程调度_python并发编程之进程、线程、协程的调度原理(六)

    进程.线程和协程的调度和运行原理总结. 系列文章 进程.线程的调度策略介绍 linux中的进程主要有三种调度策略: 优先级调度:将进程分为普通进程和实时进程: 先进先出(队列)调度:实时进程先创建的先 ...

  8. 【操作系统】进程、线程、协程和并发、并行

    文章目录 一.并发介绍 1. 进程和线程 (1)进程 (2)线程 (3)进程与线程的区别 (4)任务调度 (5)何时使用多进程,何时使用多线程? 2. 线程和协程 (1)协程 (2)协程和线程的区别 ...

  9. 从根上理解高性能、高并发(七):深入操作系统,一文读懂进程、线程、协程

    本文引用了"一文读懂什么是进程.线程.协程"一文的主要内容,感谢原作者的无私分享. 1.系列文章引言 1.1 文章目的 作为即时通讯技术的开发者来说,高性能.高并发相关的技术概念早 ...

最新文章

  1. Centos7 系统下搭建.NET Core2.0+Nginx+Supervisor+Mysql环境
  2. [转载] 扩展Python之在Python中调用C编写的函数模块
  3. 【渝粤教育】电大中专电子商务网站建设与维护 (13)作业 题库
  4. 3-4 掘金小册学习
  5. 时间序列预测算法——DeepAR
  6. JavaEye被CSDN收购
  7. 基于浏览器的3D网页游戏JavaScript 3D游戏引擎介绍
  8. 驱动ST7789 240*240 TFT屏 制作分光棱镜显示要点总结(镜像后图片颜色R、B对调了,使用PS修改图片)
  9. 解决联想电脑插入耳机没有声音问题
  10. 【深入浅出flink】第7篇:从原理剖析flink中所有的重分区方式keyBy、broadcast、rebalance、rescale、shuffle、global、partitionCustom
  11. 数据结构试卷及答案(七)
  12. Destoon 自定义模块
  13. 第十三周项目1---(4)Floyd算法验证
  14. 月老在线牵盲盒/交友盲盒/一元交友/存取小纸条盲盒/分销功能
  15. 2022-2028年全球与中国皮卡后视镜行业市场前瞻与投资战略规划分析
  16. 图片切割 - 九宫格
  17. Java中级开发笔试题及答案,最全指南
  18. effective morden c++ 3
  19. 为什么说现在是布局Filecoin的最佳时机?
  20. 我是什么情况下开始学python,现在能用python做什么

热门文章

  1. 【HTML】元素的 alt 和 title 有什么区别?
  2. 见缝插针小程序php,抖音小程序怎么开通
  3. 一个简单的物流管理系统
  4. java highchart统计图_java+highchart实现分类下钻柱形图
  5. iota 的 优点与吐槽
  6. 2021网易秋招笔试题(Android开发)
  7. 弘辽科技:拼多多改销量会影响权重吗?要注意什么事项?
  8. premiere pr 自动调色对比度 用法
  9. 无爬虫团队,企业如何实现1000万级数据采集?
  10. 装修颜色搭配方案,打造与众不同的家居