刚刚了解到这个类库,据说是个并发网络场景下非常高性能的模块
我自己写了个代码做了个测试,反而比直接使用多threading SocketServer模块更慢,是我用的有问题吗?求高手指教
我做了4组测试,分别是服务端使用/不使用eventlet 客户端使用/不使用eventlet的组合测试,结果是都不使用eventlet的一组情况最好,还请各位指教~
服务端代码
#import eventlet #eventlet.monkey_patch() #from eventlet.green import SocketServer from SocketServer import TCPServer,StreamRequestHandler,ThreadingMixIn,UnixStreamServer,BaseServer import os class myserver(ThreadingMixIn, TCPServer): #class myserver(ThreadingMixIn, UnixStreamServer): request_queue_size = 8192 allow_reuse_address = True def _remove_socket(self): pass try: os.remove(self.server_address) except OSError: pass def server_bind(self): #self._remove_socket() TCPServer.server_bind(self) def shutdown(self): TCPServer.shutdown(self) self.server_close() self._remove_socket() class requesthandler(StreamRequestHandler): def handle(self): req = '' while True: chunk = self.rfile.readline() if not chunk: break req += chunk if chunk == '\r\n': break data = 'Hello World\r\n' self.wfile.write('HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s'%(len(data),data)) def main(): #addr = './123.sock' addr = ('127.0.0.1', 81) try: server = myserver(addr,requesthandler) print server server.serve_forever(0.1) except KeyboardInterrupt: server.shutdown() main()
客户端代码
#import eventlet #eventlet.monkey_patch() import threading import blist,socket jobs = blist.blist([]) def a(): for i in xrange(100): s = socket.socket() s.connect(('127.0.0.1',81)) #s = socket.socket(socket.AF_UNIX) #s.connect('./123.sock') s.sendall('\r\n') data = '' ret = s.recv(1) while True: if ret: data += ret ret = s.recv(1) else: s.close() break cc = 300 for i in xrange(cc): jobs.append(threading.Thread(target = a)) for i in xrange(cc): jobs[i].start() for i in xrange(cc): jobs[i].join()
这个回复里部分内容基于本人猜测,所以仅供参考……
Greenlet相对于线程的优势在于Greenlet的创建销毁和切换都不需要系统调用,不涉及内核和用户态的切换。
对于你测试的情况,每个请求只产生一次输出,对Greenlet和线程来说,都是一次创建后输出少量内容立即销毁。按理说,Greenlet的创建销毁开销也比系统线程要低,所以eventlet应该快于threading。但在并发数量较小的情况,问题可能在eventlet本身的monkeypatch的实现上。
另外还有一个可能原因是多核的优势。python的线程是系统线程,虽然有GIL的存在,但IO是不受影响的,也就是说,threading可以得到多核的优势;但用eventlet的话,由于是单进程单线程,你需要再做多进程/多线程才可以使用到多核。
猜测如果每个请求的IO需要多次write或连接时间较长或10000以上的并发或开启多进程的情况,Greenlet这种轻量级线程应该还是有优势。
补充:
在我的本子上对你的例子做了下测试,明显eventlet快10%以上……