Explorar el Código

[Python] Added a benchmark test for the socketify.py Python/PyPy web framework (#7650)

* Added a benchmark test for the socketify.py Python/PyPy web framework

* removed alpine docker

* updated readme.md

* No need to manually add Date header anymore on Socketify.py
Ciro Spaciari hace 2 años
padre
commit
5c8ad47c9f

+ 64 - 0
frameworks/Python/socketify.py/README.md

@@ -0,0 +1,64 @@
+# socketify.py
+Fast WebSocket and Http/Https server using CFFI with C API from [uNetworking/uWebSockets](https://github.com/uNetworking/uWebSockets)
+
+This project aims at High Performance PyPy3 Web Development and WebSockets
+
+> This project will adapt the full capi from uNetworking/uWebSockets but for now it's just this.
+
+### Overly simple hello world app
+```python
+from socketify import App
+
+app = App()
+app.get("/", lambda res, req: res.end("Hello World socketify from Python!"))
+app.listen(3000, lambda config: print("Listening on port http://localhost:%d now\n" % config.port))
+app.run()
+```
+
+### pip install
+
+```bash
+pip install git+https://github.com/cirospaciari/socketify.py.git --global-option=build_ext
+#or specify PyPy3
+pypy3 -m pip install git+https://github.com/cirospaciari/socketify.py.git --global-option=build_ext
+#or in editable mode
+pypy3 -m pip install -e git+https://github.com/cirospaciari/socketify.py.git@main#egg=socketify
+```
+
+### Install via requirements.txt
+
+requirements.txt file content
+```text
+git+https://github.com/cirospaciari/socketify.py.git@main#socketify --global-option="build_ext"
+```
+
+install command
+```bash
+pip install -r ./requirements.txt 
+#or specify PyPy3
+pypy3 -m pip install -r ./requirements.txt 
+```
+
+### SSL version sample
+``` python
+from socketify import App, AppOptions
+
+app = App(AppOptions(key_file_name="./misc/key.pem", cert_file_name="./misc/cert.pem", passphrase="1234"))
+app.get("/", lambda res, req: res.end("Hello World socketify from Python!"))
+app.listen(3000, lambda config: print("Listening on port http://localhost:%d now\n" % config.port))
+app.run()
+```
+
+### Build local from source
+```bash
+#clone and update submodules
+git clone https://github.com/cirospaciari/socketify.py.git
+cd ./socketify.py
+git submodule update --init --recursive --remote
+#install local pip
+pypy3 -m pip install . --global-option=build_ext #--no-cache-dir is an option
+#install in editable mode
+pypy3 -m pip install -e .
+#if you want to remove
+pypy3 -m pip uninstall socketify
+```

+ 49 - 0
frameworks/Python/socketify.py/app-python3.py

@@ -0,0 +1,49 @@
+
+import threading
+import time
+import os
+
+from ujson import dumps as json
+from datetime import datetime
+
+from socketify import App
+
+def plaintext(res, req):
+    res.write_header("Server", "socketify")
+    res.write_header("Content-Type", "text/plain")
+    res.end("Hello, World!")
+
+def applicationjson(res, req):
+    res.write_header("Server", "socketify")
+    res.write_header("Content-Type", "application/json")
+    res.end(json({"message":"Hello, World!"}))
+
+
+def run_app():
+    app = App()
+    
+    app.get("/", plaintext)
+    app.get("/json", applicationjson)
+    app.get("/plaintext", plaintext)
+    app.listen(3000)
+    app.run()
+    
+def create_fork():
+    n = os.fork()
+    # n greater than 0 means parent process
+    if not n > 0:
+        run_app()
+
+def get_worker_count():
+    try:
+        return int(os.environ["WORKER_COUNT"])
+    except:
+        return 2
+
+WORKER_COUNT = get_worker_count() - 1
+
+for index in range(WORKER_COUNT):
+    create_fork()
+
+run_app()
+

+ 48 - 0
frameworks/Python/socketify.py/app.py

@@ -0,0 +1,48 @@
+
+import threading
+import time
+import os
+
+from datetime import datetime
+
+from socketify import App
+
+
+def plaintext(res, req):
+    res.write_header("Server", "socketify")
+    res.write_header("Content-Type", "text/plain")
+    res.end("Hello, World!")
+
+def applicationjson(res, req):
+    res.write_header("Server", "socketify")
+    res.end({"message":"Hello, World!"})
+
+
+def run_app():
+    app = App()
+    app.get("/", plaintext)
+    app.get("/json", applicationjson)
+    app.get("/plaintext", plaintext)
+    app.listen(3000, None)
+    app.run()
+
+def create_fork():
+    n = os.fork()
+    # n greater than 0 means parent process
+    if not n > 0:
+        run_app()
+
+def get_worker_count():
+    try:
+        return int(os.environ["WORKER_COUNT"])
+    except:
+        return 2
+
+WORKER_COUNT = get_worker_count() - 1
+
+for index in range(WORKER_COUNT):
+    create_fork()
+
+run_app()
+#sudo ./tfb --mode benchmark --test socketify.py --type plaintext
+#sudo ./tfb --mode benchmark --test socketify.py --type json --network=tfb

+ 39 - 0
frameworks/Python/socketify.py/benchmark_config.json

@@ -0,0 +1,39 @@
+{
+    "framework": "socketify.py",
+    "tests": [{
+        "default": {
+            "json_url": "/json",
+            "plaintext_url": "/plaintext",
+            "port": 3000,
+            "approach": "Realistic",
+            "classification": "Micro",
+            "database": "None",
+            "framework": "None",
+            "language": "Ruby",
+            "orm": "Raw",
+            "platform": "None",
+            "webserver": "socketify.py",
+            "os": "Linux",
+            "database_os": "Linux",
+            "display_name": "socketify.py",
+            "notes": ""
+        },
+        "python3": {
+            "json_url": "/json",
+            "plaintext_url": "/plaintext",
+            "port": 3000,
+            "approach": "Realistic",
+            "classification": "Micro",
+            "database": "None",
+            "framework": "None",
+            "language": "Ruby",
+            "orm": "Raw",
+            "platform": "None",
+            "webserver": "socketify.py-python3",
+            "os": "Linux",
+            "database_os": "Linux",
+            "display_name": "socketify.py-python3",
+            "notes": ""
+        }
+    }]
+}

+ 28 - 0
frameworks/Python/socketify.py/config.toml

@@ -0,0 +1,28 @@
+[framework]
+name = "socketify.py"
+
+[main]
+urls.plaintext = "/plaintext"
+urls.json = "/json"
+approach = "Realistic"
+classification = "Micro"
+database = "None"
+database_os = "Linux"
+os = "Linux"
+orm = "Raw"
+platform = "None"
+webserver = "socketify.py"
+versus = "None"
+
+[python3]
+urls.plaintext = "/plaintext"
+urls.json = "/json"
+approach = "Realistic"
+classification = "Micro"
+database = "None"
+database_os = "Linux"
+os = "Linux"
+orm = "Raw"
+platform = "None"
+webserver = "socketify.py-python3"
+versus = "None"

+ 2 - 0
frameworks/Python/socketify.py/requirements-python3.txt

@@ -0,0 +1,2 @@
+git+https://github.com/cirospaciari/socketify.py.git@main#socketify --global-option="build_ext"
+ujson

+ 1 - 0
frameworks/Python/socketify.py/requirements.txt

@@ -0,0 +1 @@
+git+https://github.com/cirospaciari/socketify.py.git@main#socketify --global-option="build_ext"

+ 14 - 0
frameworks/Python/socketify.py/socketify.py-python3.dockerfile

@@ -0,0 +1,14 @@
+FROM python:3.11-rc
+
+WORKDIR /usr/src/app
+
+COPY requirements-python3.txt ./
+RUN apt-get update
+RUN apt install libuv1-dev -y
+RUN pip install --no-cache-dir -r requirements-python3.txt
+
+COPY . .
+
+EXPOSE 3000
+
+CMD WORKER_COUNT=$(nproc) python ./app-python3.py

+ 15 - 0
frameworks/Python/socketify.py/socketify.py.dockerfile

@@ -0,0 +1,15 @@
+FROM pypy:3.8
+
+WORKDIR /usr/src/app
+
+COPY requirements.txt ./
+
+RUN apt-get update
+RUN apt install libuv1-dev -y
+RUN pip install --no-cache-dir -r requirements.txt
+
+COPY . .
+
+EXPOSE 3000
+
+CMD WORKER_COUNT=$(nproc) pypy3 ./app.py