#!/usr/bin/env python # coding: utf-8 # In[1]: import os import signal import gunicorn.app.base from multiprocessing import Process from contextlib import contextmanager HOST, PORT = "127.0.0.1", "8080" class BenchmarkApplication(gunicorn.app.base.BaseApplication): def __init__(self, app, worker_class, threads): self.worker_class = worker_class self.threads = threads self.application = app super().__init__() def load_config(self): self.cfg.set("bind", f"{HOST}:{PORT}") self.cfg.set("workers", 2) self.cfg.set("worker_class", self.worker_class) self.cfg.set("threads", self.threads) def load(self): return self.application def run(app_func, worker, threads): app = app_func() BenchmarkApplication(app, worker, threads).run() @contextmanager def app_running(app_func, worker, threads=1): p = Process(target=lambda: run(app_func, worker, threads)) p.start() time.sleep(1) print("allowed sleep") yield os.kill(p.pid, signal.SIGINT) print("kill sent") p.join(timeout=5) # In[4]: get_ipython().run_line_magic('matplotlib', 'inline') import time from multiprocessing import Process class Stats: def __init__(self): self.request_latencies = [] self.timed_out = 0 self.elapsed_time = 0 async def fetch(stats, session, url): start_time = time.time() try: async with session.get(url) as response: await response.text() except: stats.timed_out += 1 else: elapsed_time = time.time() - start_time stats.request_latencies.append(elapsed_time) import aiohttp TOTAL_COUNT = 5000 MAX_CONNECTIONS = 200 async def benchmark(root="http://localhost:8080/"): url = root + "foo" stats = Stats() start_time = time.time() conn = aiohttp.TCPConnector(limit=MAX_CONNECTIONS) async with aiohttp.ClientSession(connector=conn) as session: task_list = [] for i in range(TOTAL_COUNT): task_list.append(fetch(stats, session, url)) await asyncio.gather(*task_list) elapsed_time = time.time() - start_time stats.elapsed_time = elapsed_time return stats # In[ ]: from aiohttp import web import asyncio def create_aiohttp_app(): loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) async def handle(request): name = request.match_info.get('name', "Anonymous") await asyncio.sleep(0.1) text = "Hello, " + name return web.Response(text=text) aiohttp_app = web.Application() aiohttp_app.router.add_get('/', handle) aiohttp_app.router.add_get('/{name}', handle) return aiohttp_app import asyncio loop = asyncio.get_event_loop() with app_running(create_aiohttp_app, "aiohttp.worker.GunicornWebWorker"): stats = loop.run_until_complete(benchmark()) import matplotlib.pyplot as plt print(stats.elapsed_time) plt.hist(stats.request_latencies, bins=100) # In[3]: from flask import Flask flask_app = Flask(__name__) import time @flask_app.route("/") def hello(name): time.sleep(0.1) return "Hello World!" import asyncio loop = asyncio.get_event_loop() with app_running(lambda: flask_app, "sync", threads=10): stats = loop.run_until_complete(benchmark()) import matplotlib.pyplot as plt print(stats.elapsed_time) plt.hist(stats.request_latencies, bins=100) # In[ ]: