Skip to content

Instantly share code, notes, and snippets.

@thrau
Last active July 31, 2022 11:45
Show Gist options
  • Save thrau/75b84b0d501575eb50bdf1795844d6d8 to your computer and use it in GitHub Desktop.
Save thrau/75b84b0d501575eb50bdf1795844d6d8 to your computer and use it in GitHub Desktop.
investigate hypercorn asyncio performance

Run the server

Install dependencies:

pip install quart hypercorn uvloop uvicorn

To compare hypercorn, uvicorn, and hypercorn using uvloop, run (in separate terminals)

python -m localstack.aws.asgi hypercorn 4566
python -m localstack.aws.asgi uvicorn 4567 
python -m localstack.aws.asgi hypercorn_uvloop 4568

Run the benchmark

Then use benchmark.py and edit the ports array to [4566, 4567, 4567], and run the script.

Using hey

You can also use hey

hey -c 1 -H "Connection: keep-alive" http://localhost:4567
import timeit
import requests
port = 4566
session = requests.Session()
def send_get_request():
return session.get(f"http://localhost:{port}/")
def main():
global port
for p in [4566, 4567]:
port = p
print(f"GET / :{port} ms/op", (timeit.timeit(send_get_request, number=100) / 100) * 1000)
if __name__ == '__main__':
main()
import asyncio
import sys
from quart import Quart, request, Response
app = Quart(__name__)
@app.route("/", methods=["POST", "GET"])
async def sqs_list_queues():
data = await request.data
await asyncio.sleep(0.005)
return Response(
'<?xml version=\'1.0\' encoding=\'utf-8\'?>\n<ListQueuesResponse xmlns="http://queue.amazonaws.com/doc/2012-11-05/"><ListQueuesResult /><ResponseMetadata><RequestId>Y05BFPBE0ZMIURXXPY35R57NELYBSPCNY6XBU0FR0A6ITR27LZUJ</RequestId></ResponseMetadata></ListQueuesResponse>',
status=200,
headers={"Connection": "keep-alive"}
)
def run_uvicorn(port: int):
import uvicorn
uvicorn.run("server:app", port=port, log_level="info")
def run_quart(port: int):
app.run(port=port)
def run_hypercorn(port: int):
from hypercorn.asyncio import serve
from hypercorn.config import Config
config = Config()
config.bind = [f"localhost:{port}"]
asyncio.run(serve(app, config))
def run_hypercorn_uvloop(port: int):
import uvloop
uvloop.install()
from hypercorn.asyncio import serve
from hypercorn.config import Config
config = Config()
config.bind = [f"localhost:{port}"]
asyncio.run(serve(app, config))
def main():
server = sys.argv[1]
port = int(sys.argv[2])
fn = globals()[f'run_{server}']
fn(port)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment