317. Pypy launchers

Add explicit PyPy launchers for manual execution.

Lesson 317 of 356 · tests/chapter_10_performance/test_317_pypy_launchers.py

Files to create at repository root

launcher.sh
launcher.cmd

Why this step exists

PyPy can improve emulator-core throughput because much of the emulator is Python code running in tight loops. Instead of changing pyproject.toml or forcing all students to use PyPy by default, this step adds explicit manual launchers.

After creating these launchers, students should use them for manual performance experiments instead of launching main.py directly with CPython.

Linux/macOS usage

sh launcher.sh

or, if executable permission was added:

chmod +x launcher.sh
./launcher.sh

Windows Command Prompt usage

launcher.cmd

Expected manual signal

The FPS counter added earlier should improve when the emulator core benefits from PyPy. After the faster pygame framebuffer upload path, PyPy may make the emulator run faster than real NES speed. During tutorial development, the combined faster pygame drawing path plus PyPy reached roughly 90-120 FPS on the manual ROM path.

The exact number depends on machine and ROM state, but the terminal FPS output is now the evidence to compare:

fps=30.0    # example after faster pygame drawing on CPython
fps=100.0   # example after faster pygame drawing + PyPy launcher

If FPS is now above NES speed, that is good evidence that the next step should add frame pacing / expected-speed control so the manual game does not run too fast.

Expected command delegated by both launchers

uv run --python pypy python main.py

Linux/macOS example

#!/usr/bin/env sh

# Run NES with PyPy through uv.
# Usage:
#     sh launcher.sh
# or:
#     chmod +x launcher.sh
#     ./launcher.sh

uv run --python pypy python main.py

Windows CMD example

@echo off

REM Run NES with PyPy through uv.
REM Usage:
REM     launcher.cmd

uv run --python pypy python main.py

Important testing rule

These tests must not execute the launchers. Running them would start the manual pygame frontend and require a local ROM file. We only inspect the files as text.

Out of scope

  • changing pyproject.toml default Python
  • launching PyPy from pytest
  • opening pygame windows
  • measuring FPS
  • optimizing rendering

Run this lesson

uv run pytest tests/chapter_10_performance/test_317_pypy_launchers.py -v