Skip to content

Instantly share code, notes, and snippets.

@Kfir-G
Last active September 22, 2024 12:18
Show Gist options
  • Select an option

  • Save Kfir-G/c04659467de03dfe90b32356a4a11ea5 to your computer and use it in GitHub Desktop.

Select an option

Save Kfir-G/c04659467de03dfe90b32356a4a11ea5 to your computer and use it in GitHub Desktop.
Unleash the Power of FastAPI: Async vs Blocking I/O

README

Running the Example

  1. Install dependencies:

    pip install fastapi uvicorn
  2. Start the FastAPI server:

    uvicorn your_filename:app --reload
  3. Visit the following URLs to test:

    • /blocking: Waits for 5 seconds due to blocking I/O.
    • /non-blocking: Also waits for 5 seconds, but it's non-blocking and won't prevent the server from handling other requests.
    • /compare: Runs two async I/O operations concurrently and returns after both complete.
    • /benchmark: Demonstrates handling multiple concurrent requests efficiently.

Explanation

  1. Blocking I/O Example:

    • The /blocking endpoint uses a traditional synchronous def function with time.sleep(), which blocks the thread for 5 seconds.
    • This blocks the entire server, meaning no other requests will be processed during the sleep.
  2. Non-Blocking I/O Example:

    • The /non-blocking endpoint uses async def and asyncio.sleep(), which does not block the thread.
    • Other requests can be processed while this operation is waiting.
  3. Compare Endpoint:

    • We use asyncio.gather() to run two non-blocking_io operations concurrently.
    • This shows how FastAPI handles concurrent operations within a single request.
  4. Benchmark Endpoint:

    • The /benchmark endpoint simulates handling 10 concurrent requests by creating 10 non-blocking tasks and running them simultaneously.
import uvicorn
import time
import asyncio
from fastapi import FastAPI
app = FastAPI()
# Blocking I/O using def and time.sleep
@app.get("/blocking")
def blocking_io():
time.sleep(5) # This simulates a blocking I/O operation
return {"message": "Blocking I/O completed"}
# Non-blocking I/O using async def and asyncio.sleep
@app.get("/non-blocking")
async def non_blocking_io():
await asyncio.sleep(5) # This simulates a non-blocking I/O operation
return {"message": "Non-blocking I/O completed"}
# Comparison endpoint to show concurrency with async
@app.get("/compare")
async def compare():
await asyncio.gather(non_blocking_io(), non_blocking_io())
return {"message": "Both async operations completed concurrently"}
# Benchmark endpoint for handling multiple requests
@app.get("/benchmark")
async def benchmark():
tasks = [non_blocking_io() for _ in range(10)]
await asyncio.gather(*tasks)
return {"message": "Handled 10 concurrent requests!"}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment