| name | vita-profiling |
| description | Profile geometrizer on Vita3K — perf/DRC stat lines (opt-in triggers), gprof, scheduler tuning. Covers build configurations, deployment, and interpreting results. |
Vita3K Profiling
Build Configurations
The Vita build profile is selected by the GEO_VITA_PROFILE CMake option,
not CMAKE_BUILD_TYPE:
GEO_VITA_PROFILE | Flags | Use case |
|---|
| OFF (default) | -O3 -flto, -DGEO_VITA_RELEASE (logs/perf printf compiled out) | Shipping build; fastest, silent |
| ON | -g -pg -DGEO_PROFILE + vita-gprof + NOASLR, no LTO | gprof + runtime perf overlay |
Release build (default — normal testing / shipping):
cmake -B build-vita -DVITA=ON \
-DCMAKE_TOOLCHAIN_FILE=$VITASDK/share/vita.toolchain.cmake \
&& cmake --build build-vita -j
Profile build (gprof + perf overlay on Vita):
cmake -B build-vita-prof -DVITA=ON -DGEO_VITA_PROFILE=ON \
-DCMAKE_TOOLCHAIN_FILE=$VITASDK/share/vita.toolchain.cmake \
&& cmake --build build-vita-prof -j
The default Vita build is now a true release: -O3 -flto, -pg/gprof
stripped out, and all geo_log/perf-window sceClibPrintf output compiled
out via -DGEO_VITA_RELEASE. You MUST pass -DGEO_VITA_PROFILE=ON to get
gmon.out, the SELECT-button gprof hooks, or the on-TTY perf lines.
LTO is force-disabled in the Profile build because it eliminates/reorders
the mcount calls -pg injects. The release build uses GCC's plugin-aware
gcc-ar/gcc-ranlib so LTO objects archive correctly.
ARM libco backend (arm.c) is faster than sce (SceFiber) — add
-DVITA_LIBCO_BACKEND=arm unless debugging fiber issues.
Deployment to Vita3K
Vita3K filesystem on macOS:
~/Library/Application Support/Vita3K/Vita3K/fs/
ux0/app/GEOM00001/ ← deployed VPK contents
ux0/data/geometrizer/ ← runtime data (writable)
Deploy script (one-liner):
FS="$HOME/Library/Application Support/Vita3K/Vita3K/fs"
APP="$FS/ux0/app/GEOM00001"
rm -rf "$APP" && mkdir -p "$APP"
unzip -o build-prof-armco/geometrizer.vpk -d "$APP" >/dev/null
Trigger Files (ux0:data/geometrizer/)
All runtime knobs are files in the data directory — no need to rebuild:
| File | Purpose | Content |
|---|
gpu_tilemaps | Enable GPU tilemap backend (empty file) | — |
sched_max_slice | Override scheduler timeslice | Integer, e.g. 1000 |
drc_stats | Opt-in since 2026-07-10 (b8c1e4d): DRC/TGPDRC line every 30 frames + on-exit dumps | ≠ 0 |
perf_fibers | Opt-in since 2026-07-10: per-fiber PERF line (clock read per co_switch — real overhead) | ≠ 0 |
perf_log | Force the fps/cpu/video perf line on the release eboot | — |
mix_log / audio_dump | Audio pacing counters / rendered-audio dump — see vita-hw-deploy §4b | — |
nvram/vr.bin | NVRAM save (auto-created) | Binary |
Create a trigger:
FS="$HOME/Library/Application Support/Vita3K/Vita3K/fs"
touch "$FS/ux0/data/geometrizer/drc_stats"
printf "1000\n" > "$FS/ux0/data/geometrizer/sched_max_slice"
All this instrumentation used to be ON by default and is now opt-in — a
release eboot with no trigger files emits nothing and pays no counter cost.
Perf lines
Location: the perf/DRC lines go to sceClibPrintf (stderr), NOT to a file:
Vita3K captures them in its own vita3k.log; on real HW you need catlog (see
vita-hw-deploy §4). The old ux0:data/geometrizer/perf.log file sink was
removed (per-line open/write/close was pure overhead).
Format (one line per 30-frame window):
fps=48.4 cpu=19.07ms video=1.43ms
fps — measured over the 30-frame window (wall clock)
cpu — average time for model1_run_frame + model1_prepare_render + model1_end_frame (V60, TGP, M68K, scheduler)
video — average time for model1_video_update + model1_video_present (software 3D, tilemaps, upload)
DRC stats (when the drc_stats trigger is present):
DRC new_blocks=0 total_exec=374760 jit_blocks=374760 ir_blocks=0 jit_cov=100.0% jit_cycle_cov=100.0%
new_blocks — new V60 IR blocks translated this window (0 = fully cached)
total_exec — total V60 blocks executed (JIT + IR)
jit_blocks / ir_blocks — blocks run via JIT vs IR interpreter
jit_cov — percentage of blocks compiled to JIT
jit_cycle_cov — percentage of cycles executed via JIT
Interpreting the perf lines
| Pattern | Diagnosis |
|---|
cpu high, video low | CPU bottleneck (V60, TGP, M68K, scheduler) |
cpu low, video high | Video bottleneck (software 3D, tilemaps, upload) |
new_blocks > 0 for many windows | DRC cache thrashing (new code paths) |
jit_cov < 100% | JIT rejections (check [V60DRC] stderr log on exit) |
ir_blocks > 0 | Blocks falling back to IR interpreter |
Typical VR results (Vita3K, ARM libco, GPU tilemaps)
| Scene | FPS | CPU | Video |
|---|
| Stable (menu/idle) | ~37 | ~25ms | ~1.6ms |
| Post-menu (heavy 3D) | ~16-21 | ~42-55ms | ~5.6-7.3ms |
Instrumentation overhead is real: with the (old default-on) stats the stable
FPS read ~37 vs ~48 without. They are opt-in now — only enable what you need.
gprof (Profile builds only)
Requirements: configure with -DGEO_VITA_PROFILE=ON (adds -pg -DGEO_PROFILE + vita-gprof + NOASLR)
Output: ux0:data/geometrizer/gmon.out (written on clean exit)
Note: gmon.out is ARM (PS Vita) — you CANNOT run gprof with the macOS binary. The file is collected for future analysis with an ARM gprof tool or for comparison.
FS="$HOME/Library/Application Support/Vita3K/Vita3K/fs"
ls -la "$FS/ux0/data/geometrizer/gmon.out"
Vita3K Launch (macOS)
pkill -f Vita3K 2>/dev/null
perl -e "select(undef,undef,undef,1)"
open -a /Applications/Vita3K.app --args -l 1 -r GEOM00001 >/dev/null 2>&1
perl -e "select(undef,undef,undef,$N)"
pkill -f Vita3K 2>/dev/null
grep -E "PERF|DRC " "$HOME/Library/Application Support/Vita3K/Vita3K/vita3k.log" | tail
Full Iteration Script
FS="$HOME/Library/Application Support/Vita3K/Vita3K/fs"
APP="$FS/ux0/app/GEOM00001"
mkdir -p "$FS/ux0/data/geometrizer"
printf "1000\n" > "$FS/ux0/data/geometrizer/sched_max_slice"
touch "$FS/ux0/data/geometrizer/gpu_tilemaps"
touch "$FS/ux0/data/geometrizer/drc_stats"
touch "$FS/ux0/data/geometrizer/perf_fibers"
rm -rf "$APP" && mkdir -p "$APP"
unzip -o build-prof-armco/geometrizer.vpk -d "$APP" >/dev/null
pkill -f Vita3K 2>/dev/null
perl -e "select(undef,undef,undef,1)"
open -a /Applications/Vita3K.app --args -l 1 -r GEOM00001 >/dev/null 2>&1
perl -e "select(undef,undef,undef,35)"
pkill -f Vita3K 2>/dev/null
perl -e "select(undef,undef,undef,1)"
grep -E "PERF|DRC " "$HOME/Library/Application Support/Vita3K/Vita3K/vita3k.log" | tail
Common Gotchas
- stderr on Vita3K goes to
~/Library/Application Support/Vita3K/Vita3K/vita3k.log — NOT to a separate stderr.log. Search with grep "V60DRC" vita3k.log.
- Instrumentation is opt-in (2026-07-10, b8c1e4d): no trigger files → no PERF/DRC lines and no per-co_switch clock reads. The old per-line perf.log file sink is gone; lines go to sceClibPrintf only.
- gmon.out is ARM — cannot be analyzed with macOS
gprof. Use an ARM gprof or wait for Vita3K to expose profiling data.
- Vita3K window close vs clean exit — killing the window (⌘Q) may lose gmon.out (and anything stdio-buffered the app had open).