Tushar9802 commited on
Commit
5575d97
·
1 Parent(s): 755c379

perf(deploy): keep model resident + pre-warm to eliminate cold reload

Browse files

Diagnosis from Space runtime logs:
- GPU works; Gemma 4 E4B q4_K_M fully offloads 43/43 layers to T4.
- Inference is 47 tok/s once hot — fine.
- Cold model load (mmap 9GB from /data persistent disk into VRAM) is
~150s. Ollama's default keep_alive=5m was evicting between user calls,
so every extraction in a demo session re-paid the load cost (~200s
end-to-end).

Fix:
- OLLAMA_KEEP_ALIVE=24h via Dockerfile ENV: model stays in VRAM as long
as the container is awake. Subsequent extractions land hot (~14s).
- Pre-warm with a one-token generate at the end of entrypoint.sh so the
first user request also lands hot. Adds ~2-3 min to boot, but the
Space's app_port doesn't accept traffic until uvicorn comes up
anyway, so the user-facing boot time is the same.

Wake-from-sleep (HF gcTimeout, default 15min idle) still pays the cold
load — unavoidable on a serverless GPU host. Mitigations for the demo
are at Space-settings level (raise sleep timeout) or workflow level
(warm the Space before showing it to a judge).

Files changed (2) hide show
  1. Dockerfile +2 -1
  2. entrypoint.sh +14 -1
Dockerfile CHANGED
@@ -74,7 +74,8 @@ COPY --from=frontend-builder /build/frontend/dist ./frontend/dist
74
  ENV PORT=7860 \
75
  OLLAMA_MODEL=gemma4:e4b-it-q4_K_M \
76
  OLLAMA_MODELS=/data/.ollama/models \
77
- HF_HOME=/data/.cache/huggingface
 
78
 
79
  EXPOSE 7860
80
 
 
74
  ENV PORT=7860 \
75
  OLLAMA_MODEL=gemma4:e4b-it-q4_K_M \
76
  OLLAMA_MODELS=/data/.ollama/models \
77
+ HF_HOME=/data/.cache/huggingface \
78
+ OLLAMA_KEEP_ALIVE=24h
79
 
80
  EXPOSE 7860
81
 
entrypoint.sh CHANGED
@@ -60,10 +60,23 @@ done
60
  if ollama list | awk '{print $1}' | grep -qx "$MODEL"; then
61
  echo "[entrypoint] Model $MODEL already present, skipping pull"
62
  else
63
- echo "[entrypoint] Pulling $MODEL (first boot only — ~4GB, takes 2-5 min)..."
64
  ollama pull "$MODEL"
65
  fi
66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  # Hand off to FastAPI. uvicorn imports api:app, which imports app.py (loads
68
  # schemas eagerly via the FastAPI startup hook). Whisper model is loaded
69
  # lazily on the first audio request — keeps boot fast.
 
60
  if ollama list | awk '{print $1}' | grep -qx "$MODEL"; then
61
  echo "[entrypoint] Model $MODEL already present, skipping pull"
62
  else
63
+ echo "[entrypoint] Pulling $MODEL (first boot only — ~9GB, takes 5-15 min)..."
64
  ollama pull "$MODEL"
65
  fi
66
 
67
+ # Pre-warm the model into VRAM so the first user request doesn't pay the
68
+ # ~150s mmap cost (T4 + 9GB weights on HF persistent disk). Combined with
69
+ # OLLAMA_KEEP_ALIVE=24h in Dockerfile ENV, the model stays resident for the
70
+ # life of the container.
71
+ echo "[entrypoint] Pre-warming $MODEL into VRAM (one-shot generate, ~2-3 min on cold persistent disk)..."
72
+ WARM_START=$(date +%s)
73
+ curl -fsS http://127.0.0.1:11434/api/generate \
74
+ -H "Content-Type: application/json" \
75
+ -d "{\"model\":\"$MODEL\",\"prompt\":\"ok\",\"stream\":false,\"keep_alive\":\"24h\"}" \
76
+ >/tmp/warmup.json 2>&1 \
77
+ && echo "[entrypoint] Pre-warm done in $(($(date +%s) - WARM_START))s" \
78
+ || echo "[entrypoint] WARN: pre-warm failed — first user request will pay cold-load cost. See /tmp/warmup.json"
79
+
80
  # Hand off to FastAPI. uvicorn imports api:app, which imports app.py (loads
81
  # schemas eagerly via the FastAPI startup hook). Whisper model is loaded
82
  # lazily on the first audio request — keeps boot fast.