Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Linwei
Linwei

Posted on

     

Benchmark asyncio vs gevent vs native epoll

Everyone knows theasyncio module in python schedules all coroutines in a single thread. That means it helps you code easier, and you can't gain any performance from it.

But what is the performance of python'sasyncio module? How fast can it run compared to traditionalgevent and nativeepoll ?

Requirements

pip3installhiredis gevent
Enter fullscreen modeExit fullscreen mode

An optional packageuvloop can also be install if working on Linux:

pip3installuvloop
Enter fullscreen modeExit fullscreen mode

Source

The following code uses bothasyncio andgevent to simulate a redis server on port 5000, 5001, and 5002.

They can be tested withredis-benchmark.

content ofecho_bench_gevent.py:

importsysimportgeventimportgevent.monkeyimporthiredisfromgevent.serverimportStreamServergevent.monkey.patch_all()d={}defprocess(req):# only support get/setcmd=req[0].lower()ifcmd==b'set':d[req[1]]=req[2]returnb"+OK\r\n"elifcmd==b'get':v=d.get(req[1])ifvisNone:returnb'$-1\r\n'else:returnb'$1\r\n1\r\n'else:print(cmd)raiseNotImplementedError()returnb''defhandle(sock,addr):reader=hiredis.Reader()whileTrue:buf=sock.recv(4096)ifnotbuf:returnreader.feed(buf)whileTrue:req=reader.gets()ifnotreq:breaksock.sendall(process(req))return0print('serving on 0.0.0.0:5000')server=StreamServer(('0.0.0.0',5000),handle)server.serve_forever()
Enter fullscreen modeExit fullscreen mode

content ofecho_bench_asyncio.py:

importasyncioimporthiredisd={}defprocess(req):cmd=req[0].lower()ifcmd==b'set':d[req[1]]=req[2]returnb"+OK\r\n"elifcmd==b'get':v=d.get(req[1])ifvisNone:returnb'$-1\r\n'else:returnb'$1\r\n1\r\n'elifcmd==b'config':returnb'-ERROR\r\n'else:returnb'-ERROR\r\n'returnb''asyncdefecho_server(reader,writer):hireader=hiredis.Reader()whileTrue:s=awaitreader.read(4096)ifnots:breakhireader.feed(s)whileTrue:req=hireader.gets()ifnotreq:breakres=process(req)writer.write(res)awaitwriter.drain()return0asyncdefmain():server=awaitasyncio.start_server(echo_server,'0.0.0.0',5001)print('serving on {}'.format(server.sockets[0].getsockname()))awaitserver.serve_forever()return0asyncio.run(main())
Enter fullscreen modeExit fullscreen mode

content ofecho_bench_asyncio_uvloop.py:

importasyncioimporthiredisd={}defprocess(req):cmd=req[0].lower()ifcmd==b'set':d[req[1]]=req[2]returnb"+OK\r\n"elifcmd==b'get':v=d.get(req[1])ifvisNone:returnb'$-1\r\n'else:returnb'$1\r\n1\r\n'elifcmd==b'config':returnb'-ERROR\r\n'else:returnb'-ERROR\r\n'returnb''asyncdefecho_server(reader,writer):hireader=hiredis.Reader()whileTrue:s=awaitreader.read(4096)ifnots:breakhireader.feed(s)whileTrue:req=hireader.gets()ifnotreq:breakres=process(req)writer.write(res)awaitwriter.drain()return0asyncdefmain():server=awaitasyncio.start_server(echo_server,'0.0.0.0',5002)print('serving on {}'.format(server.sockets[0].getsockname()))awaitserver.serve_forever()return0try:importuvloopuvloop.install()print('uvloop is enabled')exceptImportError:print('uvloop is not available')asyncio.run(main())
Enter fullscreen modeExit fullscreen mode

Start servers

python3 echo_bench_gevent.py# will listen on port 5000python3 echo_bench_asyncio.py# will listen on port 5001python3 echo_bench_asyncio_uvloop.py# will listen on port 5002
Enter fullscreen modeExit fullscreen mode

Test

redis-benchmark-p 5000-t get-n 100000-r 100000000redis-benchmark-p 5001-t get-n 100000-r 100000000redis-benchmark-p 5002-t get-n 100000-r 100000000
Enter fullscreen modeExit fullscreen mode

Result

ModePython 3.9Python 3.11
gevent34281.80 requests / second32258.07 requests / second
asyncio40144.52 requests / second51652.89 requests / second
asyncio + uvloop64102.57 requests / second66577.90 requests / second

Native epoll

Redis is implemented withepoll in C, and we can test redis directly:

redis-benchmark-p 6379-t get-n 100000-r 100000000
Enter fullscreen modeExit fullscreen mode

Output:

75244.55 requests per second
Enter fullscreen modeExit fullscreen mode

Conclusion

  • asyncio is 50% faster thangevent in Python 3.11
  • asyncio can run twice as fast asgevent withuvloop.
  • asyncio can go up to 68% of a native epoll program.
  • asyncio can go up to 88% of a native epoll program withuvloop.

Top comments(2)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
blasti profile image
blastbeat
  • Joined

Thank you for the nice write-up. Using asyncio + uvloop + transports/protocols is even faster and on par with the benchmark against native Redis on my machine:

importasyncioimporthiredisd={}defprocess(req):cmd=req[0].lower()ifcmd==b'set':d[req[1]]=req[2]returnb"+OK\r\n"elifcmd==b'get':v=d.get(req[1])ifvisNone:returnb'$-1\r\n'else:returnb'$1\r\n1\r\n'elifcmd==b'config':returnb'-ERROR\r\n'else:returnb'-ERROR\r\n'returnb''classRedisServerProtocol(asyncio.Protocol):defconnection_made(self,transport):self.transport=transportself.hireader=hiredis.Reader()defdata_received(self,data):self.hireader.feed(data)whileTrue:req=self.hireader.gets()ifnotreq:breakres=process(req)self.transport.write(res)asyncdefmain():loop=asyncio.get_running_loop()server=awaitloop.create_server(lambda:RedisServerProtocol(),'0.0.0.0',5003)print('serving on {}'.format(server.sockets[0].getsockname()))asyncwithserver:awaitserver.serve_forever()try:importuvloopuvloop.install()exceptImportError:print('uvloop is not available')asyncio.run(main())
Enter fullscreen modeExit fullscreen mode

Above code gives me:

redis-benchmark -p 5003 -t get -n 100000 -r 100000000...138696.25 requests per second
Enter fullscreen modeExit fullscreen mode

compared to

redis-benchmark -p 6379 -t get -n 100000 -r 100000000...134589.50 requests per second
Enter fullscreen modeExit fullscreen mode
CollapseExpand
 
skywind3000 profile image
Linwei
Coding since 1992.
  • Location
    Shenzhen, PRC
  • Joined

unbelievable result !

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Coding since 1992.
  • Location
    Shenzhen, PRC
  • Joined

Trending onDEV CommunityHot

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp