Skip to content

MicahLyle/ft

Repository files navigation

README

Disclaimer (Read First)

  • I've only tested this on Ubuntu.
  • You might need to adopt some of the commands for Windows (I'm using Windows and I just run this in WSL).
  • A lot of the code (especially frontend) was AI-generated (with heavy guidance). If you give the @ai-notes/ folder to programs like Cursor, make sure @ai-notes/overview.md is read, it will help.
  • At the time of writing, the concurrency graph (not the waterfall, the concurrency graph) may not necessarily be correct in gunicorn or other multiprocessing scenarios since the counter is not actually shared among workers. This is a known bug/issue.
  • Lastly: Not all of the demo is or was used for the conference talk given. I explored a number of different avenues, and there are some half trodden/incomplete paths in this codebase. For example, I'm not actually using MODE as much as I was planning to. I do derive some information from it, but was going to use it to give better titles to the graphs and charts. I didn't get to that, but there's a reason most stuff is there, it's just probably not documented.

Setup

  1. git clone https://github.com/MicahLyle/ft
  2. cd ft
  3. Install uv if you haven't already.
  4. uv sync
  5. MODE=rns-sync-ft-t-314 PYTHON_GIL=0 uv run -p python3.14t nanodjango manage app.py runserver 0:8001
  6. Visit localhost:8001 and you're off to the races.

Misc Notes

  • Some of these may be out of date with the talk that was given. Some of these were things I was comparing.

Runserver

  • runserver, synchronous, GIL
    • runserver-sync-gil-t-314: MODE=rns-sync-gil-t-314 uv run -p python3.14 nanodjango manage app.py runserver 0:8000
  • runserver, synchronous, Free Threaded
    • runserver-sync-ft-t-314: MODE=rns-sync-ft-t-314 PYTHON_GIL=0 uv run -p python3.14t nanodjango manage app.py runserver 0:8000

WSGI/Sync

  • gunicorn, synchronous, GIL
    • gunicorn-sync-gil-p-314: MODE=gun-sync-gil-p-314 uv run -p python3.14 gunicorn app:wsgi --bind 0.0.0.0:8001 --workers 8 --name ft

ASGI/Async

  • gunicorn (ASGI, Uvicorn worker)
    • gunicorn-async-gil-p-314: MODE=gun-async-gil-p-314 uv run -p python3.14 gunicorn -k uvicorn.workers.UvicornWorker app:asgi --bind 0.0.0.0:8001 --workers 8 --name ft
    • gunicorn-async-ft-p-314t: MODE=gun-async-ft-p-314t PYTHON_GIL=0 uv run -p python3.14t gunicorn -k uvicorn.workers.UvicornWorker app:asgi --bind 0.0.0.0:8001 --workers 2 --name ft

(Older, Less Relevant)

Possible Modes

Runserver (sync only, worker t)

  • runserver-sync-gil-t-313: MODE=rns-sync-gil-t-313 uv run nanodjango manage app.py runserver 0:8000
  • runserver-sync-ft-t-313t: MODE=rns-sync-ft-t-313t PYTHON_GIL=0 uv run -p python3.13t nanodjango manage app.py runserver 0:8000
  • runserver-sync-gil-t-314: MODE=rns-sync-gil-t-314 uv run -p python3.14 nanodjango manage app.py runserver 0:8000
  • runserver-sync-ft-t-314t: MODE=rns-sync-ft-t-314t PYTHON_GIL=0 uv run -p python3.14t nanodjango manage app.py runserver 0:8000

Gunicorn (wsgi only, worker p)

  • gunicorn-sync-gil-p-313: MODE=gun-sync-gil-p-313 uv run gunicorn app:wsgi
  • gunicorn-sync-ft-p-313t: MODE=gun-sync-ft-p-313t PYTHON_GIL=0 uv run -p python3.13t gunicorn -k gthread app:wsgi
  • gunicorn-sync-gil-p-314: MODE=gun-sync-gil-p-314 uv run -p python3.14 gunicorn app:wsgi
  • gunicorn-sync-ft-p-314t: MODE=gun-sync-ft-p-314t PYTHON_GIL=0 uv run -p python3.14t gunicorn -k gthread app:wsgi

Gunicorn (wsgi only, worker p, optimized)

  • gunicorn-sync-gil-p-313: MODE=gun-sync-gil-p-313 uv run -p python3.13 gunicorn app:wsgi -w 8
  • gunicorn-sync-ft-p-313t: MODE=gun-sync-ft-p-313t PYTHON_GIL=0 uv run -p python3.13t gunicorn -k gthread app:wsgi -w 2 --threads 16
  • gunicorn-sync-gil-p-314: MODE=gun-sync-gil-p-314 uv run -p python3.14 gunicorn app:wsgi -w 8
  • gunicorn-sync-ft-p-314t: MODE=gun-sync-ft-p-314t PYTHON_GIL=0 uv run -p python3.14t gunicorn -k gthread app:wsgi -w 2 --threads 16

Granian (sync/async, worker t or p)

3.13

  • granian-sync-gil-t-313: MODE=gra-sync-gil-t-313 uv run -p python3.13 granian --interface wsgi --host 0.0.0.0 --port 8000 app:wsgi
  • granian-sync-gil-p-313: MODE=gra-sync-gil-p-313 uv run -p python3.13 granian --interface wsgi --host 0.0.0.0 --port 8000 app:wsgi
  • granian-async-gil-t-313: MODE=gra-async-gil-t-313 uv run -p python3.13 granian --interface asgi --host 0.0.0.0 --port 8000 app:asgi
  • granian-async-gil-p-313: MODE=gra-async-gil-p-313 uv run -p python3.13 granian --interface asgi --host 0.0.0.0 --port 8000 app:asgi

3.13t

  • granian-sync-ft-t-313t: MODE=gra-sync-ft-t-313t PYTHON_GIL=0 uv run -p python3.13t granian --interface wsgi --host 0.0.0.0 --port 8000 app:wsgi
  • granian-sync-ft-p-313t: MODE=gra-sync-ft-p-313t PYTHON_GIL=0 uv run -p python3.13t granian --interface wsgi --host 0.0.0.0 --port 8000 app:wsgi
  • granian-async-ft-t-313t: MODE=gra-async-ft-t-313t PYTHON_GIL=0 uv run -p python3.13t granian --interface asgi --host 0.0.0.0 --port 8000 app:asgi
  • granian-async-ft-p-313t: MODE=gra-async-ft-p-313t PYTHON_GIL=0 uv run -p python3.13t granian --interface asgi --host 0.0.0.0 --port 8000 app:asgi

3.14

  • granian-sync-gil-t-314: MODE=gra-sync-gil-t-314 uv run -p python3.14 granian --interface wsgi --host 0.0.0.0 --port 8000 app:wsgi
  • granian-sync-gil-p-314: MODE=gra-sync-gil-p-314 uv run -p python3.14 granian --interface wsgi --host 0.0.0.0 --port 8000 app:wsgi
  • granian-async-gil-t-314: MODE=gra-async-gil-t-314 uv run -p python3.14 granian --interface asgi --host 0.0.0.0 --port 8000 app:asgi
  • granian-async-gil-p-314: MODE=gra-async-gil-p-314 uv run -p python3.14 granian --interface asgi --host 0.0.0.0 --port 8000 app:asgi

3.14t

  • granian-sync-ft-t-314t: MODE=gra-sync-ft-t-314t PYTHON_GIL=0 uv run -p python3.14t granian --interface wsgi --host 0.0.0.0 --port 8000 app:wsgi
  • granian-sync-ft-p-314t: MODE=gra-sync-ft-p-314t PYTHON_GIL=0 uv run -p python3.14t granian --interface wsgi --host 0.0.0.0 --port 8000 app:wsgi
  • granian-async-ft-t-314t: MODE=gra-async-ft-t-314t PYTHON_GIL=0 uv run -p python3.14t granian --interface asgi --host 0.0.0.0 --port 8000 app:asgi
  • granian-async-ft-p-314t: MODE=gra-async-ft-p-314t PYTHON_GIL=0 uv run -p python3.14t granian --interface asgi --host 0.0.0.0 --port 8000 app:asgi

Granian (3.14t optimized presets)

  • gra-sync-ft-p-314t (WSGI, workers=2, runtime-threads=16, backpressure=256):
    MODE=gra-sync-ft-p-314t PYTHON_GIL=0 uv run -p python3.14t granian --interface wsgi --host 0.0.0.0 --port 8000 --workers 2 --runtime-threads 16 --backpressure 256 app:wsgi
  • gra-sync-ft-mt-314t (WSGI, mt runtime, workers=2, runtime-threads=16, backpressure=256):
    MODE=gra-sync-ft-mt-314t PYTHON_GIL=0 uv run -p python3.14t granian --interface wsgi --host 0.0.0.0 --port 8000 --workers 2 --runtime-threads 16 --backpressure 256 --runtime mt app:wsgi
  • gra-async-ft-p-314t (ASGI, workers=2, runtime-threads=8, backpressure=512):
    MODE=gra-async-ft-p-314t PYTHON_GIL=0 uv run -p python3.14t granian --interface asgi --host 0.0.0.0 --port 8000 --workers 2 --runtime-threads 8 --backpressure 512 app:asgi

About

Django Free Threading Experiments

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •