• 协程


    协程具有极高的执行效率,因为子程序切换不是线程切换,而是由程序控制,
    没有线程切换的开销,和多线程比,线程数量越多,性能优势越明显。
    因为只有一个线程,不存在同时写变量冲突,在协程中控制共享资源只需要判断状态,
    不必加锁,故执行效率比多线程高。
    协程是一个线程执行,使用多进程+协程,可充分利用多核CPU,获得极佳性能。


    【1】yield实现协程(生产者消费者)
    Python通过yield提供了对协程的基本支持,但是不完全。

     1 import time
     2 
     3 def consumer(name):
     4     print("准备")
     5     while True:
     6         result = yield
     7         print("[%s] 消费 %s" % (name,result))
     8         #time.sleep(1)
     9 
    10 def producer():
    11 
    12     r = con1.__next__()
    13     r = con2.__next__()
    14     n = 0
    15     while 1:
    16         time.sleep(1)
    17         print("生产者: %s and %s" %(n,n+1))
    18         con1.send(n)    #发送给yield,result得到此值。
    19         con2.send(n+1)
    20         n +=2
    21 
    22 
    23 if __name__ == '__main__':
    24     con1 = consumer("c1")  #获得生成器对象
    25     con2 = consumer("c2")
    26     p = producer()
    View Code

    【2】Greenlet 协程模块  
    greenlet是一个用C实现的协程模块,相比与python自带的yield,
    它可以使你在任意函数之间随意切换,而不需把这个函数先声明为generator。

     1 from greenlet import greenlet
     2  
     3  
     4 def test1():
     5     print(1)
     6     gr2.switch()
     7     print(3)
     8     gr2.switch()
     9  
    10  
    11 def test2():
    12     print(2)
    13     gr1.switch()
    14     print(4)
    15  
    16 if __name__ == '__main__':
    17     gr1 = greenlet(test1)
    18     gr2 = greenlet(test2)
    19     gr1.switch()
    View Code

    【3】Gevent
    Gevent是一种基于协程的第三方Python网络库,通过greenlet实现协程,非标准库,尚存在缺陷。
    在python3中有一个官网正在做并且在3.6中已经稳定的库asyncio。

    使用gevent,可以获得极高的并发性能,但gevent只能在Unix/Linux下运行。
    由于gevent是基于IO切换的协程,编写的Web App代码,不需要引入gevent的包和修改代码,
    只需在部署时,用一个支持gevent的WSGI服务器,就可获得数倍的性能提升。

    ★过程:
    当一个greenlet遇到IO操作时,就自动切换到其他的greenlet,等到IO操作完成,再切换回来。
    Gevent直接修改标准库里面大部分的阻塞式系统调用,包括socket、ssl、threading和 select等模块,而变为协作式运行,这一过程在启动时通过monkey patch(猴子补丁)完成:

     1 #例:
     2 from gevent import monkey; monkey.patch_socket()
     3 import gevent
     4 
     5 def f(n):
     6     for i in range(n):
     7         print gevent.getcurrent(), i
     8         gevent.sleep(1) #sleep模拟IO
     9 
    10 g1 = gevent.spawn(f, 5)
    11 g2 = gevent.spawn(f, 5)
    12 g3 = gevent.spawn(f, 5)
    13 g1.join()
    14 g2.join()
    15 g3.join()
    16 
    17 #例:
    18 from gevent import monkey; monkey.patch_all()
    19 import gevent
    20 import urllib2
    21 import time
    22 start=time.time()
    23 
    24 def f(url):
    25     print('GET: %s' % url)
    26     resp = urllib2.urlopen(url)
    27     data = resp.read()
    28     print('%d bytes received from %s.' % (len(data), url))
    29 
    30 gevent.joinall([
    31         gevent.spawn(f, 'https://www.python.org/'),
    32         gevent.spawn(f, 'https://www.baidu.com/'),
    33         gevent.spawn(f, 'https://github.com/'),
    34 ])    
    35     
    36 print("cost time:",time.time()-start)
    View Code
  • 相关阅读:
    使用FRP让内网站点被外网访问
    游戏AI(三)—行为树优化之基于事件的行为树
    游戏AI(二)—行为树优化之内存优化
    游戏AI-行为树理论及实现
    利用InfluxDB和Grafana搭建一个数据监测的仪表盘
    Go语言中slice使用注意事项
    4:ELK分析tomcat日志
    2:tomcat配置优化
    文件操作2-Day3
    MySQL读写分离项目配置
  • 原文地址:https://www.cnblogs.com/mountain2011/p/11361029.html
Copyright © 2020-2023  润新知