diff --git a/frameworks/Python/aiohttp/aiohttp-gunicorn.dockerfile b/frameworks/Python/aiohttp/aiohttp-gunicorn.dockerfile index 6fb96c40f5a..71c8048b2af 100644 --- a/frameworks/Python/aiohttp/aiohttp-gunicorn.dockerfile +++ b/frameworks/Python/aiohttp/aiohttp-gunicorn.dockerfile @@ -4,11 +4,10 @@ ADD ./ /aiohttp WORKDIR aiohttp -RUN pip3 install cython==3.0.11 gunicorn==23.0.0 && \ - pip3 install -r /aiohttp/requirements.txt +RUN pip3 install -r /aiohttp/requirements-cpython.txt ENV CONNECTION=RAW EXPOSE 8080 -CMD python3 -O -m gunicorn app.gunicorn:app -c gunicorn_conf.py \ No newline at end of file +CMD python3 -O -m gunicorn app.gunicorn:app -c gunicorn_conf.py diff --git a/frameworks/Python/aiohttp/aiohttp-nginx.dockerfile b/frameworks/Python/aiohttp/aiohttp-nginx.dockerfile index 9739a8e83bd..2c96a25f9b9 100644 --- a/frameworks/Python/aiohttp/aiohttp-nginx.dockerfile +++ b/frameworks/Python/aiohttp/aiohttp-nginx.dockerfile @@ -1,20 +1,17 @@ FROM python:3.13 -ADD ./requirements.txt /aiohttp/requirements.txt - -RUN pip3 install cython==3.0.11 && \ - pip3 install -r /aiohttp/requirements.txt - RUN apt-get update && apt-get install -y nginx ADD ./ /aiohttp WORKDIR /aiohttp +RUN pip3 install -r /aiohttp/requirements-cpython.txt + ENV CONNECTION=RAW EXPOSE 8080 RUN chmod +x /aiohttp/nginx-entrypoint.sh -ENTRYPOINT ["/aiohttp/nginx-entrypoint.sh"] \ No newline at end of file +ENTRYPOINT ["/aiohttp/nginx-entrypoint.sh"] diff --git a/frameworks/Python/aiohttp/aiohttp-orm.dockerfile b/frameworks/Python/aiohttp/aiohttp-orm.dockerfile index c113afcd7d5..c63f3e1689e 100644 --- a/frameworks/Python/aiohttp/aiohttp-orm.dockerfile +++ b/frameworks/Python/aiohttp/aiohttp-orm.dockerfile @@ -1,16 +1,13 @@ FROM python:3.13 -ADD ./requirements.txt /aiohttp/requirements.txt - -RUN pip3 install cython==3.0.11 && \ - pip3 install -r /aiohttp/requirements.txt - ADD ./ /aiohttp WORKDIR /aiohttp +RUN pip3 install -r /aiohttp/requirements-cpython.txt + ENV CONNECTION=ORM EXPOSE 8080 -CMD python3 -O -m app.server \ No newline at end of file +CMD python3 -O -m app.server diff --git a/frameworks/Python/aiohttp/aiohttp-pypy.dockerfile b/frameworks/Python/aiohttp/aiohttp-pypy.dockerfile new file mode 100644 index 00000000000..bc7770b7e7d --- /dev/null +++ b/frameworks/Python/aiohttp/aiohttp-pypy.dockerfile @@ -0,0 +1,13 @@ +FROM pypy:3.11 + +ADD ./ /aiohttp + +WORKDIR /aiohttp + +RUN pip3 install -r /aiohttp/requirements.txt + +ENV CONNECTION=RAW + +EXPOSE 8080 + +CMD python3 -O -m app.server diff --git a/frameworks/Python/aiohttp/aiohttp.dockerfile b/frameworks/Python/aiohttp/aiohttp.dockerfile index a9ecfff8c07..3edfb605a1c 100644 --- a/frameworks/Python/aiohttp/aiohttp.dockerfile +++ b/frameworks/Python/aiohttp/aiohttp.dockerfile @@ -1,16 +1,13 @@ FROM python:3.13 -ADD ./requirements.txt /aiohttp/requirements.txt - -RUN pip3 install cython==3.0.11 && \ - pip3 install -r /aiohttp/requirements.txt - ADD ./ /aiohttp WORKDIR /aiohttp +RUN pip3 install -r /aiohttp/requirements-cpython.txt + ENV CONNECTION=RAW EXPOSE 8080 -CMD python3 -O -m app.server \ No newline at end of file +CMD python3 -O -m app.server diff --git a/frameworks/Python/aiohttp/app/app.py b/frameworks/Python/aiohttp/app/app.py index ae8b74c1414..40d33382e10 100644 --- a/frameworks/Python/aiohttp/app/app.py +++ b/frameworks/Python/aiohttp/app/app.py @@ -1,11 +1,15 @@ -import uvloop -from aiohttp import web import argparse +import platform + +from aiohttp import web + from .main import create_app if __name__ == '__main__': - uvloop.install() + if platform.python_implementation() != "PyPy": + import uvloop + uvloop.install() parser = argparse.ArgumentParser() parser.add_argument('--socket', type=str, required=True) args = parser.parse_args() diff --git a/frameworks/Python/aiohttp/app/main.py b/frameworks/Python/aiohttp/app/main.py index ef2b2fd4f8b..f334f2ca8a2 100644 --- a/frameworks/Python/aiohttp/app/main.py +++ b/frameworks/Python/aiohttp/app/main.py @@ -1,7 +1,7 @@ -import os import multiprocessing +import os +import platform -import asyncpg from aiohttp import web from sqlalchemy.engine.url import URL from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine @@ -20,6 +20,15 @@ updates_raw, ) +if platform.python_implementation() != "PyPy": + import asyncpg + + class NoResetConnection(asyncpg.Connection): + __slots__ = () + + def get_reset_query(self): + return "" + CONNECTION_ORM = os.getenv('CONNECTION', 'ORM').upper() == 'ORM' @@ -37,12 +46,6 @@ def pg_dsn(dialect=None) -> str: ) return url.render_as_string(hide_password=False) -class NoResetConnection(asyncpg.Connection): - __slots__ = () - - def get_reset_query(self): - return '' - async def db_ctx(app: web.Application): # number of gunicorn workers = multiprocessing.cpu_count() as per gunicorn_conf.py # max_connections = 2000 as per toolset/setup/linux/databases/postgresql/postgresql.conf:64 @@ -84,6 +87,7 @@ def setup_routes(app): def create_app(): app = web.Application() - app.cleanup_ctx.append(db_ctx) + if platform.python_implementation() != "PyPy": + app.cleanup_ctx.append(db_ctx) setup_routes(app) return app diff --git a/frameworks/Python/aiohttp/app/server.py b/frameworks/Python/aiohttp/app/server.py index d28000daaee..c1f48b3d4be 100644 --- a/frameworks/Python/aiohttp/app/server.py +++ b/frameworks/Python/aiohttp/app/server.py @@ -1,9 +1,11 @@ +import multiprocessing import os +import platform import socket -import multiprocessing + from aiohttp import web + from .main import create_app -import uvloop SERVERS_COUNT = multiprocessing.cpu_count() BACKLOG = 2048 @@ -12,7 +14,9 @@ def start_server(sock, cpu_id): if hasattr(os, "sched_setaffinity"): os.sched_setaffinity(0, {cpu_id}) - uvloop.install() + if platform.python_implementation() != "PyPy": + import uvloop + uvloop.install() app = create_app() web.run_app(app, sock=sock, backlog=BACKLOG, access_log=None) @@ -43,4 +47,4 @@ def create_reusable_socket(host='0.0.0.0', port=8080): workers.append(worker) for worker in workers: - worker.join() \ No newline at end of file + worker.join() diff --git a/frameworks/Python/aiohttp/app/views.py b/frameworks/Python/aiohttp/app/views.py index c743cc47054..e52d4255744 100644 --- a/frameworks/Python/aiohttp/app/views.py +++ b/frameworks/Python/aiohttp/app/views.py @@ -1,15 +1,26 @@ +import platform from operator import attrgetter, itemgetter from pathlib import Path from random import randint, sample import jinja2 from aiohttp.web import Response -from orjson import dumps from sqlalchemy import bindparam, select from sqlalchemy.orm.attributes import flag_modified from .models import Fortune, World +if platform.python_implementation() == "PyPy": + from aiohttp.web import json_response +else: + from orjson import dumps + + def json_response(payload): + return Response( + body=dumps(payload), + content_type="application/json", + ) + ADDITIONAL_FORTUNE_ORM = Fortune(id=0, message='Additional fortune added at request time.') ADDITIONAL_FORTUNE_ROW = {'id': 0, 'message': 'Additional fortune added at request time.'} READ_ROW_SQL = 'SELECT "randomnumber", "id" FROM "world" WHERE id = $1' @@ -25,8 +36,8 @@ def get_num_queries(request): try: - num_queries = int(request.match_info.get('queries', 1)) - except ValueError: + num_queries = int(request.match_info['queries']) + except (KeyError, ValueError): return 1 if num_queries < 1: return 1 @@ -35,13 +46,6 @@ def get_num_queries(request): return num_queries -def json_response(payload): - return Response( - body=dumps(payload), - content_type="application/json", - ) - - async def json(request): """ Test 1 diff --git a/frameworks/Python/aiohttp/benchmark_config.json b/frameworks/Python/aiohttp/benchmark_config.json index 366ff434220..487ab2fc7cc 100644 --- a/frameworks/Python/aiohttp/benchmark_config.json +++ b/frameworks/Python/aiohttp/benchmark_config.json @@ -23,6 +23,25 @@ "display_name": "aiohttp", "notes": "uses asyncpg for database access" }, + "pypy": { + "json_url": "/json", + "plaintext_url": "/plaintext", + "port": 8080, + "approach": "Realistic", + "classification": "Micro", + "database": "Postgres", + "framework": "aiohttp", + "language": "Python", + "flavor": "Pypy3", + "orm": "Raw", + "platform": "asyncio", + "webserver": "None", + "os": "Linux", + "database_os": "Linux", + "display_name": "aiohttp-pypy", + "notes": "uses Pypy instead of CPython", + "versus": "default" + }, "nginx": { "json_url": "/json", "db_url": "/db", @@ -43,7 +62,8 @@ "os": "Linux", "database_os": "Linux", "display_name": "aiohttp-nginx", - "notes": "uses nginx as proxy" + "notes": "uses nginx as proxy", + "versus": "default" }, "gunicorn": { "json_url": "/json", diff --git a/frameworks/Python/aiohttp/config.toml b/frameworks/Python/aiohttp/config.toml index 195a408ba2e..47a6c33bb28 100644 --- a/frameworks/Python/aiohttp/config.toml +++ b/frameworks/Python/aiohttp/config.toml @@ -18,6 +18,19 @@ platform = "asyncio" webserver = "None" versus = "None" +[pypy] +urls.plaintext = "/plaintext" +urls.json = "/json" +approach = "Realistic" +classification = "Micro" +database = "Postgres" +database_os = "Linux" +os = "Linux" +orm = "Raw" +platform = "asyncio" +webserver = "None" +versus = "default" + [nginx] urls.plaintext = "/plaintext" urls.json = "/json" diff --git a/frameworks/Python/aiohttp/requirements-cpython.txt b/frameworks/Python/aiohttp/requirements-cpython.txt new file mode 100644 index 00000000000..f49e01d17d2 --- /dev/null +++ b/frameworks/Python/aiohttp/requirements-cpython.txt @@ -0,0 +1,6 @@ +-r requirements.txt + +asyncpg==0.30.0 +gunicorn==23.0.0 +orjson==3.10.16 +uvloop==0.21.0 diff --git a/frameworks/Python/aiohttp/requirements.txt b/frameworks/Python/aiohttp/requirements.txt index 7729cae3c1d..0142f9212d2 100644 --- a/frameworks/Python/aiohttp/requirements.txt +++ b/frameworks/Python/aiohttp/requirements.txt @@ -1,6 +1,3 @@ aiohttp==3.11.18 -asyncpg==0.30.0 jinja2==3.1.6 SQLAlchemy==2.0.40 -orjson==3.10.16 -uvloop==0.21.0