python 64式: 第37式、eventlet并发性能探究

1 eventlet性能探究
测试代码如下:
# -*- encoding: utf-8 -*-

from datetime import datetime
import time

import eventlet

eventlet.monkey_patch()

# eventlet.monkey_patch(all=False,
#                       os=True,
#                       select=True,
#                       socket=True,
#                       thread=False,
#                       time=True)

def timeHelper(func):
    def wrapper(*args, **kwargs):
        try:
            start = datetime.now()
            info = "############ function: {func} Begin , start: {start} ##########" .format(
                func=func.__name__,
                start=str(start))
            print info
            result = func(*args, **kwargs)
            end = datetime.now()
            diff = end - start
            info = "##### function: {func} End , end: {end}, cost time: {cost} #####" .format(
                func=func.__name__,
                end=str(end),
                cost=str(diff))
            print info
            return result
        except Exception as ex:
            info = "Exception type is %s, message is %s" % (ex.__class__.__name__, ex)
            print info
    return wrapper


def func1():
    time.sleep(3)
    info = "func1 time: {curTime}".format(
        curTime=datetime.now()
    )
    print info


def func2():
    time.sleep(3)
    info = "func2 time: {curTime}".format(
        curTime=datetime.now()
    )
    print info

@timeHelper
def useEventlet():
    pool = eventlet.GreenPool()
    pool.spawn(func1)
    pool.spawn(func2)
    pool.waitall()

@timeHelper
def notUseEventlet():
    func1()
    func2()

def process():
    notUseEventlet()
    useEventlet()


if __name__ == "__main__":
    process()


分析:
这里用sleep方法来模拟I/O密集型任务


2 实验结果
未使用eventlet的执行结果:
############ function: notUseEventlet Begin , start: 2019-09-18 15:53:28.481971 ##########
func1 time: 2019-09-18 15:53:31.485827
func2 time: 2019-09-18 15:53:34.487574
##### function: notUseEventlet End , end: 2019-09-18 15:53:34.487858, cost time: 0:00:06.005887 #####

使用eventlet.monkey_patch()的执行结果:
############ function: useEventlet Begin , start: 2019-09-18 15:54:01.934679 ##########
func1 time: 2019-09-18 15:54:04.938762
func2 time: 2019-09-18 15:54:04.939150
##### function: useEventlet End , end: 2019-09-18 15:54:04.939206, cost time: 0:00:03.004527 #####

使用
eventlet.monkey_patch(all=False,
                      os=True,
                      select=True,
                      socket=True,
                      thread=False,
                      time=True)
的执行结果:
############ function: useEventlet Begin , start: 2019-09-18 15:56:29.513413 ##########
func1 time: 2019-09-18 15:56:32.515038
func2 time: 2019-09-18 15:56:32.515170
##### function: useEventlet End , end: 2019-09-18 15:56:32.515231, cost time: 0:00:03.001818 #####

3 结论
3.1 使用eventlet可以通过相互渡让cpu来实现并发,不使用eventlet,则程序变成串行并且性能较差。
3.2 使用
eventlet.monkey_patch()

eventlet.monkey_patch(all=False,
                      os=True,
                      select=True,
                      socket=True,
                      thread=False,
                      time=True)
在性能上一般没有区别。

4 python性能优化
如果在某个方法中同时调用多个api,并且没有使用eventlet,则该方法中每个api串行执行,
性能较差。
建议使用eventlet.GreenPool来对多个api并发执行来提升性能。
代码样例如下:
import eventlet
eventlet.monkey_patch()

def useEventlet():
    pool = eventlet.GreenPool()
    pool.spawn(func1, arg1)
    pool.spawn(func2, arg2)
    pool.waitall()

其中可以设置arg1为结果参数,即初始化arg1是空的,
然后在func1中将执行的结果赋值给arg1,这样就解决了eventlet.GreenPool.spawn无返回值的问题。


参考:
https://www.cnblogs.com/Security-Darren/p/4168233.html
https://wenku.baidu.com/view/e695e811fe4733687e21aaed.html
https://blog.csdn.net/hzrandd/article/details/11815323
 

上一篇:eventlet设置超时时间


下一篇:Python中多线程编程的优点是什么?