• python 同步与异步的性能区别及实例


     同步与异步的性能区别 

    1.

    #coding:utf-8
    import gevent 
    def task(pid):
        """
        Some non-deterministic task
        """
        gevent.sleep(0.5) #起到切换的作用
        print('Task %s done' % pid) 
    def synchronous():
        for i in range(1,10):
            task(i) 
    def asynchronous():
        threads = [gevent.spawn(task, i) for i in range(10)]
        gevent.joinall(threads) #等待所以操作都执行完毕 
    print('Synchronous:')
    synchronous() #同步 
    print('Asynchronous:')
    asynchronous()#异步  这里会按照sleep 设置来执行
    

    2.Python通过yield提供了对协程的基本支持,但是不完全。而第三方的gevent为Python提供了比较完善的协程支持。

    gevent是第三方库,通过greenlet实现协程,其基本思想是:

    当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。1.可用使用gevent.sleep()调整执行顺序也可以2.使用monkey patch来修改标准库,不改原始代码的方式调整。

    由于切换是在IO操作时自动完成,所以gevent需要修改Python自带的一些标准库,这一过程在启动时通过monkey patch完成:

    遇到IO阻塞时会自动切换任务

    #coding:utf-8
    from urllib import urlopen
    import gevent
    from  gevent  import monkey;monkey.patch_all()  #修改标准库,使IO操作时,还会继续执行其他的协程
    
    def t(n):
        print n
        url=urlopen(n)  #遇到IO操作都会自动执行其他协程
        urll=url.read()
        print 'len%s,url%s'%(len(urll),n)
    gevent.joinall([
        gevent.spawn(t,'https://www.cnblogs.com/iexperience/p/9342446.html'),
        gevent.spawn(t,'https://www.cnblogs.com/iexperience/p/9329362.html'),
        gevent.spawn(t,'https://www.cnblogs.com/iexperience/p/9329332.html'),
        ])
    

    结果:

    https://www.cnblogs.com/iexperience/p/9342446.html
    https://www.cnblogs.com/iexperience/p/9329362.html
    https://www.cnblogs.com/iexperience/p/9329332.html
    len10649,urlhttps://www.cnblogs.com/iexperience/p/9342446.html
    len12980,urlhttps://www.cnblogs.com/iexperience/p/9329362.html
    len7646,urlhttps://www.cnblogs.com/iexperience/p/9329332.html

    从结果看,3个网络操作是并发执行的,而且结束顺序不同,但只有一个线程。

    要让greenlet交替运行,可以通过gevent.sleep()交出控制权,像开始的实例1中的异步一样:

    参考:https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001407503089986d175822da68d4d6685fbe849a0e0ca35000

    通过gevent来实现单线程下的多socket并发

    server 端,采用gevent协程

    import sys
    import socket
    import time
    import gevent 
    from gevent import socket,monkey
    monkey.patch_all()  
    def server(port):
        s = socket.socket()
        s.bind(('0.0.0.0', port))
        s.listen(500)
        while True:
            cli, addr = s.accept()
            gevent.spawn(handle_request, cli)   #gevent.spwan调用handle参数并传参  
     
    def handle_request(conn):
        try:
            while True:
                data = conn.recv(1024)
                print("recv:", data)
                conn.send(data)
                if not data:             
                    conn.shutdown(socket.SHUT_WR)
     
        except Exception as  ex:
            print(ex)
        finally:
            conn.close()
    if __name__ == '__main__':
        server(8001)
    

    client端

    单线程的客户端

    import socket
     
    HOST = 'localhost'    # The remote host
    PORT = 8001           # The same port as used by the server
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((HOST, PORT))
    while True:
        msg = bytes(input(">>:"),encoding="utf8")
        s.sendall(msg)
        data = s.recv(1024)
        #print(data)
     
        print('Received', repr(data))
    s.close()
    

    多线程客户端去请求

    import socket
    import threading
    def sock_conn():
        client = socket.socket()
        client.connect(("localhost",8001))
        count = 0
        while True:
            #msg = input(">>:").strip()
            #if len(msg) == 0:continue
            client.send( ("hello %s" %count).encode("utf-8"))
    
            data = client.recv(1024)
    
            print("[%s]recv from server:" % threading.get_ident(),data.decode()) #结果
            count +=1
        client.close()
    
    for i in range(100):
        t = threading.Thread(target=sock_conn)
        t.start()
    
  • 相关阅读:
    XMLHttpRequest简介
    BC30138: 无法在路径“C:\WINDOWS\TEMP\”中创建临时文件: 拒绝访问。
    开机explorer无法启动,无法进入桌面
    选择DataGrid中的CheckBox控件后该行背景变色
    CSS菜单制作工具
    ScriptX打印控件的使用
    JS实时预览上传图片缩略图
    readyState的五种状态详解
    xmlHttpRequest的status的值的含义
    C#调用word打印
  • 原文地址:https://www.cnblogs.com/iexperience/p/9368814.html
Copyright © 2020-2023  润新知