Skip to content

Commit 8ec5b77

Browse files
Dreamsorcererlitongjava
authored andcommitted
Aiohttp: Add pypy3 and minor optimisation (TechEmpower#9903)
* Aiohttp: minor optimisation * Create aiohttp-pypy.dockerfile * Update benchmark_config.json * Update config.toml * Update aiohttp-pypy.dockerfile * Update aiohttp-gunicorn.dockerfile * Update aiohttp-nginx.dockerfile * Update aiohttp-orm.dockerfile * Update aiohttp.dockerfile * Update requirements.txt * Create requirements-cpython.txt * Update aiohttp-gunicorn.dockerfile * Update aiohttp-nginx.dockerfile * Update aiohttp-orm.dockerfile * Update aiohttp.dockerfile * Update views.py * Update aiohttp-nginx.dockerfile * Update aiohttp-orm.dockerfile * Update aiohttp-pypy.dockerfile * Update aiohttp.dockerfile * Update requirements.txt * Update requirements-cpython.txt * Update app.py * Update config.toml * Update main.py * Update requirements.txt * Update requirements-cpython.txt * Update main.py * Update server.py * Update benchmark_config.json * Update aiohttp-gunicorn.dockerfile * Update aiohttp-nginx.dockerfile * Update aiohttp-orm.dockerfile * Update aiohttp-pypy.dockerfile * Update aiohttp.dockerfile * Update requirements-cpython.txt * Update aiohttp-gunicorn.dockerfile * Update aiohttp-nginx.dockerfile * Update aiohttp-orm.dockerfile * Update aiohttp-pypy.dockerfile * Update aiohttp.dockerfile * Update aiohttp-pypy.dockerfile
1 parent 92ad429 commit 8ec5b77

File tree

13 files changed

+106
-51
lines changed

13 files changed

+106
-51
lines changed

frameworks/Python/aiohttp/aiohttp-gunicorn.dockerfile

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@ ADD ./ /aiohttp
44

55
WORKDIR aiohttp
66

7-
RUN pip3 install cython==3.0.11 gunicorn==23.0.0 && \
8-
pip3 install -r /aiohttp/requirements.txt
7+
RUN pip3 install -r /aiohttp/requirements-cpython.txt
98

109
ENV CONNECTION=RAW
1110

1211
EXPOSE 8080
1312

14-
CMD python3 -O -m gunicorn app.gunicorn:app -c gunicorn_conf.py
13+
CMD python3 -O -m gunicorn app.gunicorn:app -c gunicorn_conf.py
Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
FROM python:3.13
22

3-
ADD ./requirements.txt /aiohttp/requirements.txt
4-
5-
RUN pip3 install cython==3.0.11 && \
6-
pip3 install -r /aiohttp/requirements.txt
7-
83
RUN apt-get update && apt-get install -y nginx
94

105
ADD ./ /aiohttp
116

127
WORKDIR /aiohttp
138

9+
RUN pip3 install -r /aiohttp/requirements-cpython.txt
10+
1411
ENV CONNECTION=RAW
1512

1613
EXPOSE 8080
1714

1815
RUN chmod +x /aiohttp/nginx-entrypoint.sh
1916

20-
ENTRYPOINT ["/aiohttp/nginx-entrypoint.sh"]
17+
ENTRYPOINT ["/aiohttp/nginx-entrypoint.sh"]
Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
FROM python:3.13
22

3-
ADD ./requirements.txt /aiohttp/requirements.txt
4-
5-
RUN pip3 install cython==3.0.11 && \
6-
pip3 install -r /aiohttp/requirements.txt
7-
83
ADD ./ /aiohttp
94

105
WORKDIR /aiohttp
116

7+
RUN pip3 install -r /aiohttp/requirements-cpython.txt
8+
129
ENV CONNECTION=ORM
1310

1411
EXPOSE 8080
1512

16-
CMD python3 -O -m app.server
13+
CMD python3 -O -m app.server
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
FROM pypy:3.11
2+
3+
ADD ./ /aiohttp
4+
5+
WORKDIR /aiohttp
6+
7+
RUN pip3 install -r /aiohttp/requirements.txt
8+
9+
ENV CONNECTION=RAW
10+
11+
EXPOSE 8080
12+
13+
CMD python3 -O -m app.server
Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
FROM python:3.13
22

3-
ADD ./requirements.txt /aiohttp/requirements.txt
4-
5-
RUN pip3 install cython==3.0.11 && \
6-
pip3 install -r /aiohttp/requirements.txt
7-
83
ADD ./ /aiohttp
94

105
WORKDIR /aiohttp
116

7+
RUN pip3 install -r /aiohttp/requirements-cpython.txt
8+
129
ENV CONNECTION=RAW
1310

1411
EXPOSE 8080
1512

16-
CMD python3 -O -m app.server
13+
CMD python3 -O -m app.server

frameworks/Python/aiohttp/app/app.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
import uvloop
2-
from aiohttp import web
31
import argparse
2+
import platform
3+
4+
from aiohttp import web
5+
46
from .main import create_app
57

68

79
if __name__ == '__main__':
8-
uvloop.install()
10+
if platform.python_implementation() != "PyPy":
11+
import uvloop
12+
uvloop.install()
913
parser = argparse.ArgumentParser()
1014
parser.add_argument('--socket', type=str, required=True)
1115
args = parser.parse_args()

frameworks/Python/aiohttp/app/main.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import os
21
import multiprocessing
2+
import os
3+
import platform
34

4-
import asyncpg
55
from aiohttp import web
66
from sqlalchemy.engine.url import URL
77
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
@@ -20,6 +20,15 @@
2020
updates_raw,
2121
)
2222

23+
if platform.python_implementation() != "PyPy":
24+
import asyncpg
25+
26+
class NoResetConnection(asyncpg.Connection):
27+
__slots__ = ()
28+
29+
def get_reset_query(self):
30+
return ""
31+
2332
CONNECTION_ORM = os.getenv('CONNECTION', 'ORM').upper() == 'ORM'
2433

2534

@@ -37,12 +46,6 @@ def pg_dsn(dialect=None) -> str:
3746
)
3847
return url.render_as_string(hide_password=False)
3948

40-
class NoResetConnection(asyncpg.Connection):
41-
__slots__ = ()
42-
43-
def get_reset_query(self):
44-
return ''
45-
4649
async def db_ctx(app: web.Application):
4750
# number of gunicorn workers = multiprocessing.cpu_count() as per gunicorn_conf.py
4851
# max_connections = 2000 as per toolset/setup/linux/databases/postgresql/postgresql.conf:64
@@ -84,6 +87,7 @@ def setup_routes(app):
8487

8588
def create_app():
8689
app = web.Application()
87-
app.cleanup_ctx.append(db_ctx)
90+
if platform.python_implementation() != "PyPy":
91+
app.cleanup_ctx.append(db_ctx)
8892
setup_routes(app)
8993
return app

frameworks/Python/aiohttp/app/server.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
import multiprocessing
12
import os
3+
import platform
24
import socket
3-
import multiprocessing
5+
46
from aiohttp import web
7+
58
from .main import create_app
6-
import uvloop
79

810
SERVERS_COUNT = multiprocessing.cpu_count()
911
BACKLOG = 2048
@@ -12,7 +14,9 @@
1214
def start_server(sock, cpu_id):
1315
if hasattr(os, "sched_setaffinity"):
1416
os.sched_setaffinity(0, {cpu_id})
15-
uvloop.install()
17+
if platform.python_implementation() != "PyPy":
18+
import uvloop
19+
uvloop.install()
1620
app = create_app()
1721

1822
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):
4347
workers.append(worker)
4448

4549
for worker in workers:
46-
worker.join()
50+
worker.join()

frameworks/Python/aiohttp/app/views.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,26 @@
1+
import platform
12
from operator import attrgetter, itemgetter
23
from pathlib import Path
34
from random import randint, sample
45

56
import jinja2
67
from aiohttp.web import Response
7-
from orjson import dumps
88
from sqlalchemy import bindparam, select
99
from sqlalchemy.orm.attributes import flag_modified
1010

1111
from .models import Fortune, World
1212

13+
if platform.python_implementation() == "PyPy":
14+
from aiohttp.web import json_response
15+
else:
16+
from orjson import dumps
17+
18+
def json_response(payload):
19+
return Response(
20+
body=dumps(payload),
21+
content_type="application/json",
22+
)
23+
1324
ADDITIONAL_FORTUNE_ORM = Fortune(id=0, message='Additional fortune added at request time.')
1425
ADDITIONAL_FORTUNE_ROW = {'id': 0, 'message': 'Additional fortune added at request time.'}
1526
READ_ROW_SQL = 'SELECT "randomnumber", "id" FROM "world" WHERE id = $1'
@@ -25,8 +36,8 @@
2536

2637
def get_num_queries(request):
2738
try:
28-
num_queries = int(request.match_info.get('queries', 1))
29-
except ValueError:
39+
num_queries = int(request.match_info['queries'])
40+
except (KeyError, ValueError):
3041
return 1
3142
if num_queries < 1:
3243
return 1
@@ -35,13 +46,6 @@ def get_num_queries(request):
3546
return num_queries
3647

3748

38-
def json_response(payload):
39-
return Response(
40-
body=dumps(payload),
41-
content_type="application/json",
42-
)
43-
44-
4549
async def json(request):
4650
"""
4751
Test 1

frameworks/Python/aiohttp/benchmark_config.json

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,25 @@
2323
"display_name": "aiohttp",
2424
"notes": "uses asyncpg for database access"
2525
},
26+
"pypy": {
27+
"json_url": "/json",
28+
"plaintext_url": "/plaintext",
29+
"port": 8080,
30+
"approach": "Realistic",
31+
"classification": "Micro",
32+
"database": "Postgres",
33+
"framework": "aiohttp",
34+
"language": "Python",
35+
"flavor": "Pypy3",
36+
"orm": "Raw",
37+
"platform": "asyncio",
38+
"webserver": "None",
39+
"os": "Linux",
40+
"database_os": "Linux",
41+
"display_name": "aiohttp-pypy",
42+
"notes": "uses Pypy instead of CPython",
43+
"versus": "default"
44+
},
2645
"nginx": {
2746
"json_url": "/json",
2847
"db_url": "/db",
@@ -43,7 +62,8 @@
4362
"os": "Linux",
4463
"database_os": "Linux",
4564
"display_name": "aiohttp-nginx",
46-
"notes": "uses nginx as proxy"
65+
"notes": "uses nginx as proxy",
66+
"versus": "default"
4767
},
4868
"gunicorn": {
4969
"json_url": "/json",

0 commit comments

Comments
 (0)