From: Sam Mirazi Date: Tue, 3 Jun 2025 19:05:36 +0000 (-0700) Subject: 23 X-Git-Url: https://git.josue.xyz/?a=commitdiff_plain;h=ba8b3faa81064717ecb19b971ffba6c3720dd18f;p=fastapi-vs-flask%2F.git 23 --- diff --git a/app_fastapi/FastAPI_no_delay.py b/app_fastapi/FastAPI_no_delay.py new file mode 100644 index 0000000..36959b4 --- /dev/null +++ b/app_fastapi/FastAPI_no_delay.py @@ -0,0 +1,13 @@ +# app_fastapi/app_no_delay.py +from fastapi import FastAPI, Response +# import asyncio # No longer needed for sleep + +app = FastAPI() + +@app.get("/") +async def home(): + # await asyncio.sleep(0.3) # Removed delay + html = "

FastAPI Server: No Artificial Delay

" + return Response(content=html, media_type="text/html") + +# To run this app (for testing): uvicorn app_fastapi.app_no_delay:app --reload --port 8000 \ No newline at end of file diff --git a/app_fastapi/FastAPI_with_delay.py b/app_fastapi/FastAPI_with_delay.py new file mode 100644 index 0000000..554881d --- /dev/null +++ b/app_fastapi/FastAPI_with_delay.py @@ -0,0 +1,11 @@ +# app_fastapi/app.py +from fastapi import FastAPI, Response +import asyncio + +app = FastAPI() + +@app.get("/") +async def home(): + await asyncio.sleep(0.3) # simulate slow work (non-blocking, changed from 3s to 0.3s) + html = "

FastAPI Server: 0.3-Seconds Artificial Delay Demo

" + return Response(content=html, media_type="text/html") \ No newline at end of file diff --git a/app_fastapi/__init__.py b/app_fastapi/__init__.py new file mode 100644 index 0000000..0177da3 --- /dev/null +++ b/app_fastapi/__init__.py @@ -0,0 +1 @@ +# This file makes app_fastapi a Python package \ No newline at end of file diff --git a/app_fastapi/__pycache__/FastAPI_with_delay.cpython-312.pyc b/app_fastapi/__pycache__/FastAPI_with_delay.cpython-312.pyc new file mode 100644 index 0000000..06bd888 Binary files /dev/null and b/app_fastapi/__pycache__/FastAPI_with_delay.cpython-312.pyc differ diff --git a/app_fastapi/__pycache__/__init__.cpython-312.pyc b/app_fastapi/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..c425468 Binary files /dev/null and b/app_fastapi/__pycache__/__init__.cpython-312.pyc differ diff --git a/app_fastapi/app.py b/app_fastapi/app.py deleted file mode 100644 index 554881d..0000000 --- a/app_fastapi/app.py +++ /dev/null @@ -1,11 +0,0 @@ -# app_fastapi/app.py -from fastapi import FastAPI, Response -import asyncio - -app = FastAPI() - -@app.get("/") -async def home(): - await asyncio.sleep(0.3) # simulate slow work (non-blocking, changed from 3s to 0.3s) - html = "

FastAPI Server: 0.3-Seconds Artificial Delay Demo

" - return Response(content=html, media_type="text/html") \ No newline at end of file diff --git a/app_fastapi/app_no_delay.py b/app_fastapi/app_no_delay.py deleted file mode 100644 index 36959b4..0000000 --- a/app_fastapi/app_no_delay.py +++ /dev/null @@ -1,13 +0,0 @@ -# app_fastapi/app_no_delay.py -from fastapi import FastAPI, Response -# import asyncio # No longer needed for sleep - -app = FastAPI() - -@app.get("/") -async def home(): - # await asyncio.sleep(0.3) # Removed delay - html = "

FastAPI Server: No Artificial Delay

" - return Response(content=html, media_type="text/html") - -# To run this app (for testing): uvicorn app_fastapi.app_no_delay:app --reload --port 8000 \ No newline at end of file diff --git a/app_flask/Flask_no_delay.py b/app_flask/Flask_no_delay.py new file mode 100644 index 0000000..a7b8ba0 --- /dev/null +++ b/app_flask/Flask_no_delay.py @@ -0,0 +1,33 @@ +from flask import Flask, Response +# import time # No longer needed for sleep +# import webbrowser # Not needed here +from datetime import datetime + +app = Flask(__name__) + +request_counter = 0 + +@app.route("/") +def home(): + global request_counter + request_id = request_counter + 1 + request_counter = request_id + + start_time = datetime.now() + # print(f"[Flask No-Delay Server] Request {request_id} received at {start_time.strftime('%Y-%m-%d %H:%M:%S.%f')}") # Optional: keep for debugging if needed + + # time.sleep(0.3) # Removed delay + + end_time = datetime.now() + processing_time = (end_time - start_time).total_seconds() + # print(f"[Flask No-Delay Server] Request {request_id} finishing at {end_time.strftime('%Y-%m-%d %H:%M:%S.%f')}, processed in {processing_time:.2f}s") # Optional + + html = f"

Flask Server (No Delay, Threaded): Request {request_id} processed in {processing_time:.6f}s

" + return Response(html, mimetype="text/html") + +if __name__ == "__main__": + print("[Flask No-Delay Server] Starting server on http://127.0.0.1:3000...") + # Running with threaded=True to allow Werkzeug to handle requests concurrently + app.run(host="0.0.0.0", port=3000, threaded=True) + +# To run this app (for testing): python app_flask/flask_application_no_delay.py \ No newline at end of file diff --git a/app_flask/Flask_with_delay.py b/app_flask/Flask_with_delay.py new file mode 100644 index 0000000..904643e --- /dev/null +++ b/app_flask/Flask_with_delay.py @@ -0,0 +1,37 @@ +from flask import Flask, Response +import time +import webbrowser +from datetime import datetime # Added for timestamping + +app = Flask(__name__) + +request_counter = 0 # Global counter + +@app.route("/") +def home(): + global request_counter + request_id = request_counter + 1 + request_counter = request_id + + start_time = datetime.now() + print(f"[Flask Server] Request {request_id} received at {start_time.strftime('%Y-%m-%d %H:%M:%S.%f')}") + + time.sleep(0.3) # simulate slow work + + end_time = datetime.now() + processing_time = (end_time - start_time).total_seconds() + print(f"[Flask Server] Request {request_id} finishing at {end_time.strftime('%Y-%m-%d %H:%M:%S.%f')}, processed in {processing_time:.2f}s") + + html = f"

Flask Server: Request {request_id} processed in {processing_time:.2f}s

" # Updated content + return Response(html, mimetype="text/html") + +if __name__ == "__main__": + print("[Flask Server] Starting server on http://127.0.0.1:3000...") + # host = "127.0.0.1" # Not strictly needed for app.run with 0.0.0.0 + # port = 3000 # Port is defined in app.run + # url = f"http://{host}:{port}/" # Not needed as webbrowser call is removed + + # Open the URL in a new browser tab # THIS LINE WILL BE REMOVED + # webbrowser.open_new_tab(url) # REMOVED + + app.run(host="0.0.0.0", port=3000, threaded=False) # Port 3000, explicitly single-threaded \ No newline at end of file diff --git a/app_flask/flask_application.py b/app_flask/flask_application.py deleted file mode 100644 index 904643e..0000000 --- a/app_flask/flask_application.py +++ /dev/null @@ -1,37 +0,0 @@ -from flask import Flask, Response -import time -import webbrowser -from datetime import datetime # Added for timestamping - -app = Flask(__name__) - -request_counter = 0 # Global counter - -@app.route("/") -def home(): - global request_counter - request_id = request_counter + 1 - request_counter = request_id - - start_time = datetime.now() - print(f"[Flask Server] Request {request_id} received at {start_time.strftime('%Y-%m-%d %H:%M:%S.%f')}") - - time.sleep(0.3) # simulate slow work - - end_time = datetime.now() - processing_time = (end_time - start_time).total_seconds() - print(f"[Flask Server] Request {request_id} finishing at {end_time.strftime('%Y-%m-%d %H:%M:%S.%f')}, processed in {processing_time:.2f}s") - - html = f"

Flask Server: Request {request_id} processed in {processing_time:.2f}s

" # Updated content - return Response(html, mimetype="text/html") - -if __name__ == "__main__": - print("[Flask Server] Starting server on http://127.0.0.1:3000...") - # host = "127.0.0.1" # Not strictly needed for app.run with 0.0.0.0 - # port = 3000 # Port is defined in app.run - # url = f"http://{host}:{port}/" # Not needed as webbrowser call is removed - - # Open the URL in a new browser tab # THIS LINE WILL BE REMOVED - # webbrowser.open_new_tab(url) # REMOVED - - app.run(host="0.0.0.0", port=3000, threaded=False) # Port 3000, explicitly single-threaded \ No newline at end of file diff --git a/app_flask/flask_application_no_delay.py b/app_flask/flask_application_no_delay.py deleted file mode 100644 index a7b8ba0..0000000 --- a/app_flask/flask_application_no_delay.py +++ /dev/null @@ -1,33 +0,0 @@ -from flask import Flask, Response -# import time # No longer needed for sleep -# import webbrowser # Not needed here -from datetime import datetime - -app = Flask(__name__) - -request_counter = 0 - -@app.route("/") -def home(): - global request_counter - request_id = request_counter + 1 - request_counter = request_id - - start_time = datetime.now() - # print(f"[Flask No-Delay Server] Request {request_id} received at {start_time.strftime('%Y-%m-%d %H:%M:%S.%f')}") # Optional: keep for debugging if needed - - # time.sleep(0.3) # Removed delay - - end_time = datetime.now() - processing_time = (end_time - start_time).total_seconds() - # print(f"[Flask No-Delay Server] Request {request_id} finishing at {end_time.strftime('%Y-%m-%d %H:%M:%S.%f')}, processed in {processing_time:.2f}s") # Optional - - html = f"

Flask Server (No Delay, Threaded): Request {request_id} processed in {processing_time:.6f}s

" - return Response(html, mimetype="text/html") - -if __name__ == "__main__": - print("[Flask No-Delay Server] Starting server on http://127.0.0.1:3000...") - # Running with threaded=True to allow Werkzeug to handle requests concurrently - app.run(host="0.0.0.0", port=3000, threaded=True) - -# To run this app (for testing): python app_flask/flask_application_no_delay.py \ No newline at end of file diff --git a/run_benchmark_NO_RESTRICTIONS.py b/run_benchmark_NO_RESTRICTIONS.py index d9a1b3e..46a5148 100644 --- a/run_benchmark_NO_RESTRICTIONS.py +++ b/run_benchmark_NO_RESTRICTIONS.py @@ -222,20 +222,23 @@ def display_table(rows): SCENARIOS = [ { "name": "FastAPI (No Delay)", - "config": "Uvicorn, async (41 workers)", + "config": "Uvicorn, async (1 worker, httptools)", "delay": "None", - "cmd": ["uvicorn", "app_fastapi.app_no_delay:app", "--host", "0.0.0.0", - "--port", "8000", "--log-level", "warning", "--workers", "41"], + "cmd": ["uvicorn", "app_fastapi.FastAPI_no_delay:app", "--host", "0.0.0.0", + "--port", "8000", "--log-level", "warning", + "--workers", "1", + "--http", "httptools" + ], "url": FASTAPI_SERVER_URL, - "bench_arg": "fastapi", # benchmark/run_benchmark.py uses this to pick the URL/method + "bench_arg": "fastapi", }, { "name": "Flask (No Delay, Threaded)", "config": "Werkzeug (threaded=True)", "delay": "None", - "cmd": [PYTHON_EXE, "app_flask/flask_application_no_delay.py"], + "cmd": [PYTHON_EXE, "app_flask/Flask_no_delay.py"], "url": FLASK_SERVER_URL, - "bench_arg": "flask", # benchmark/run_benchmark.py uses this to pick the URL/method + "bench_arg": "flask", } ] diff --git a/run_benchmark_table.py b/run_benchmark_table.py index c8801b9..0f72361 100644 --- a/run_benchmark_table.py +++ b/run_benchmark_table.py @@ -24,9 +24,9 @@ def start_server(command_args, health_check_url, server_name, cwd=None): console.print(f"[yellow]Starting {server_name} server…[/yellow]") # --- STREAM HANDLING: inherit console so the child can always write - popen_kwargs = dict(cwd=cwd, text=True, - stdout=subprocess.DEVNULL, - stderr=subprocess.STDOUT) + popen_kwargs = dict(cwd=cwd, text=True) + # stdout=subprocess.DEVNULL, # Temporarily allow stdout + # stderr=subprocess.STDOUT # Temporarily allow stderr # run either as "python -m uvicorn ..." or plain exe if "uvicorn" in command_args[0] and not command_args[0].endswith(".exe"): @@ -196,10 +196,10 @@ def display_table(rows): SCENARIOS = [ { "name": "FastAPI", - "config": "Uvicorn, async", + "config": "Uvicorn, async (default worker, h11, debug log)", "delay": "0.3 s asyncio.sleep", - "cmd": ["uvicorn", "app_fastapi.app:app", "--host", "0.0.0.0", - "--port", "8000", "--log-level", "warning"], + "cmd": ["uvicorn", "app_fastapi.FastAPI_with_delay:app", "--host", "0.0.0.0", + "--port", "8000", "--log-level", "debug", "--http", "h11"], "url": FASTAPI_SERVER_URL, "bench_arg": "fastapi", }, @@ -207,7 +207,7 @@ SCENARIOS = [ "name": "Flask", "config": "Single-threaded, synchronous", "delay": "0.3 s time.sleep", - "cmd": [PYTHON_EXE, "app_flask/flask_application.py"], + "cmd": [PYTHON_EXE, "app_flask/Flask_with_delay.py"], "url": FLASK_SERVER_URL, "bench_arg": "flask", }