您好,匿名用户
随意问技术百科期待您的加入

使用eventlet之后反而性能更差的一组测试例子,求解为什么是这样?

0 投票

刚刚了解到这个类库,据说是个并发网络场景下非常高性能的模块
我自己写了个代码做了个测试,反而比直接使用多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()
用户头像 提问 2014年 3月1日 @ Fiora 上等兵 (297 威望)
分享到:

1个回答

0 投票

这个回复里部分内容基于本人猜测,所以仅供参考……

Greenlet相对于线程的优势在于Greenlet的创建销毁和切换都不需要系统调用,不涉及内核和用户态的切换。

对于你测试的情况,每个请求只产生一次输出,对Greenlet和线程来说,都是一次创建后输出少量内容立即销毁。按理说,Greenlet的创建销毁开销也比系统线程要低,所以eventlet应该快于threading。但在并发数量较小的情况,问题可能在eventlet本身的monkeypatch的实现上。

另外还有一个可能原因是多核的优势。python的线程是系统线程,虽然有GIL的存在,但IO是不受影响的,也就是说,threading可以得到多核的优势;但用eventlet的话,由于是单进程单线程,你需要再做多进程/多线程才可以使用到多核。

猜测如果每个请求的IO需要多次write或连接时间较长或10000以上的并发或开启多进程的情况,Greenlet这种轻量级线程应该还是有优势。

补充:
在我的本子上对你的例子做了下测试,明显eventlet快10%以上……

用户头像 回复 2014年 3月1日 @ Olaf 上等兵 (366 威望)
提一个问题:

相关问题

0 投票
1 回复 38 阅读
0 投票
1 回复 38 阅读
用户头像 提问 2013年 9月23日 @ Fizz 上等兵 (325 威望)
0 投票
1 回复 36 阅读
0 投票
1 回复 30 阅读
用户头像 提问 2012年 12月1日 @ Hepheastus 上等兵 (182 威望)

欢迎来到随意问技术百科, 这是一个面向专业开发者的IT问答网站,提供途径助开发者查找IT技术方案,解决程序bug和网站运维难题等。
温馨提示:本网站禁止用户发布与IT技术无关的、粗浅的、毫无意义的或者违法国家法规的等不合理内容,谢谢支持。

欢迎访问随意问技术百科,为了给您提供更好的服务,请及时反馈您的意见。
...