瀏覽代碼

[Python] Update Granian to 2.5, remove "wrk" variant, add "nogil" variant (#10177)

Giovanni Barillari 1 周之前
父節點
當前提交
43edfc13fb

+ 42 - 0
frameworks/Python/granian/app_rsgi_nogil.py

@@ -0,0 +1,42 @@
+import json
+
+JSON_HEADERS = [('content-type', 'application/json')]
+PLAINTEXT_HEADERS = [('content-type', 'text/plain; charset=utf-8')]
+
+# json_dumps = orjson.dumps
+json_dumps = json.dumps
+
+
+async def route_json(scope, proto):
+    proto.response_str(
+        200,
+        JSON_HEADERS,
+        json_dumps({'message': 'Hello, world!'})
+    )
+
+
+async def route_plaintext(scope, proto):
+    proto.response_bytes(
+        200,
+        PLAINTEXT_HEADERS,
+        b'Hello, world!'
+    )
+
+
+async def handle_404(scope, proto):
+    proto.response_bytes(
+        404,
+        PLAINTEXT_HEADERS,
+        b'Not found'
+    )
+
+
+routes = {
+    '/json': route_json,
+    '/plaintext': route_plaintext
+}
+
+
+def main(scope, proto):
+    handler = routes.get(scope.path, handle_404)
+    return handler(scope, proto)

+ 2 - 2
frameworks/Python/granian/benchmark_config.json

@@ -63,7 +63,7 @@
       "notes": "",
       "versus": "uvicorn"
     },
-    "wrk": {
+    "nogil": {
       "json_url": "/json",
       "plaintext_url": "/plaintext",
       "port": 8080,
@@ -77,7 +77,7 @@
       "webserver": "granian",
       "os": "Linux",
       "database_os": "Linux",
-      "display_name": "granian [rsgi wrk]",
+      "display_name": "granian [rsgi nogil]",
       "notes": "",
       "versus": "uvicorn"
     }

+ 1 - 1
frameworks/Python/granian/config.toml

@@ -48,7 +48,7 @@ platform = "None"
 webserver = "granian"
 versus = "uvicorn"
 
-[wrk]
+[nogil]
 urls.plaintext = "/plaintext"
 urls.json = "/json"
 approach = "Realistic"

+ 16 - 0
frameworks/Python/granian/granian-nogil.dockerfile

@@ -0,0 +1,16 @@
+FROM ghcr.io/astral-sh/uv:debian-slim
+
+RUN uv python install 3.14t
+
+ENV UV_PYTHON=3.14t
+ENV PYTHON_GIL=0
+
+ADD ./ /granian
+WORKDIR /granian
+
+RUN uv venv
+RUN uv pip install -r requirements-nogil.txt
+
+EXPOSE 8080
+
+CMD uv run python run_nogil.py rsgi st

+ 2 - 2
frameworks/Python/granian/granian-rsgi.dockerfile

@@ -1,4 +1,4 @@
-FROM python:3.10-slim
+FROM python:3.13-slim
 
 ADD ./ /granian
 
@@ -8,4 +8,4 @@ RUN pip install -r /granian/requirements.txt
 
 EXPOSE 8080
 
-CMD python run.py rsgi mt
+CMD python run.py rsgi st

+ 0 - 11
frameworks/Python/granian/granian-wrk.dockerfile

@@ -1,11 +0,0 @@
-FROM python:3.10-slim
-
-ADD ./ /granian
-
-WORKDIR /granian
-
-RUN pip install -r /granian/requirements.txt
-
-EXPOSE 8080
-
-CMD python run.py rsgi st

+ 1 - 1
frameworks/Python/granian/granian-wsgi.dockerfile

@@ -1,4 +1,4 @@
-FROM python:3.10-slim
+FROM python:3.13-slim
 
 ADD ./ /granian
 

+ 2 - 2
frameworks/Python/granian/granian.dockerfile

@@ -1,4 +1,4 @@
-FROM python:3.10-slim
+FROM python:3.13-slim
 
 ADD ./ /granian
 
@@ -8,4 +8,4 @@ RUN pip install -r /granian/requirements.txt
 
 EXPOSE 8080
 
-CMD python run.py asgi mt
+CMD python run.py asgi st

+ 1 - 0
frameworks/Python/granian/requirements-nogil.txt

@@ -0,0 +1 @@
+granian[rloop]>=2.5.0,<2.6.0

+ 2 - 2
frameworks/Python/granian/requirements.txt

@@ -1,4 +1,4 @@
 asyncpg==0.30.0
-granian[uvloop]>=2.4.0,<2.5.0
+granian[uvloop]>=2.5.0,<2.6.0
 jinja2==3.1.6
-orjson==3.10.16
+orjson==3.11.3

+ 32 - 0
frameworks/Python/granian/run_nogil.py

@@ -0,0 +1,32 @@
+import multiprocessing
+import sys
+
+from granian import Granian
+
+
+if __name__ == '__main__':
+    interface = sys.argv[1]
+    runtime_mode = sys.argv[2]
+    workers = multiprocessing.cpu_count()
+
+    if interface == "rsgi":
+        #: leave 25% cpu to the Rust runtime
+        workers = round(workers * 0.75)
+
+    blocking_threads = None
+    if interface == "wsgi":
+        #: we don't run any I/O in WSGI benches
+        blocking_threads = 1
+
+    Granian(
+        f"app_{interface}_nogil:main",
+        address="0.0.0.0",
+        port=8080,
+        workers=workers,
+        runtime_mode=runtime_mode,
+        blocking_threads=blocking_threads,
+        backlog=16384,
+        interface=interface,
+        http="1",
+        websockets=False
+    ).serve()