Performance improvement plan.

This commit is contained in:
Scott Duensing 2026-07-06 19:25:55 -05:00
parent 6110f714af
commit 24b88c3ba2
9 changed files with 818 additions and 179 deletions

189
NATIVE-PERF-PLAN.md Normal file
View file

@ -0,0 +1,189 @@
# NATIVE-PERF-PLAN: match hand-coded native, per port
Directive (Scott, 2026-07-06): floor parity against the IIgs is not the
bar anymore -- "still way too slow across the board." The new target is
**each port within ~1.5x of what hand-coded native technique achieves on
that hardware**, proven by cycle-math ceilings and workload benchmark
rows, not vibes. The IIgs-floor rule remains a secondary invariant
(never ship a 68k port slower than the 65816).
Why the current table lies about games: UBER measures best-case single
ops (aligned sprite x, one tile, one call). Real games pay (a) the
alignment cliff -- only aligned-x sprite draws are compiled; other x
falls to interpreters/per-pixel walkers 3-20x slower -- and (b) a
measured ~35-50% per-call wrapper tax (dispatch + validation +
dirty-mark) around cores that are already at silicon parity, and (c)
have no batch paths, so a tilemap repaint pays that tax per tile.
Frame-budget reality check (2026-07-06 table): at 25% CPU and 50/60 Hz,
~3 sprites/frame on ST/Amiga/IIgs; a 40x25 tilemap repaint costs
~0.44-0.64s on the 68k ports. Hand-coded games on these machines did
far better. Close that gap.
Ground rules (inherited from PERF-AUDIT-PLAN, all still binding):
- Source toolchains/env.sh before any make; delete stale binaries after
.s edits; Scott owns git; style rules apply.
- Every phase is hash-gated: existing goldens stay bit-identical
(diff-uber-hashes 45/45 x4) unless a phase EXPLICITLY adds rows, in
which case new goldens are frozen only after 4-port cross-identity.
- Every phase ends with a 4-port bench + PERF.md regeneration.
- Cycle models are hypotheses; the emulator measurement decides (lesson:
the fillCircle asm probe and the 17% ST clock bug).
## Phase 0 -- Ceilings + honest workload rows [items 1+2 DONE 2026-07-06]
### Item 1 RESULT -- native-technique ceilings (cycle-math, emulator-class)
Ops/sec, hand-coded best technique per port. "Meas" = current UBER
(2026-07-06, millis clock). Gap = ceiling / measured. Full derivations
with instruction-level arithmetic are in the Phase-0 workflow reports
(session scratchpad); re-derive on demand -- the arithmetic styles were
validated where models met measurements (ST present model 53/sec vs 56
measured; IIgs 29/sec present ceiling already in PERF.md).
| Op (16x16 sprite, 8x8 tile) | ST ceiling | meas | Amiga ceiling | meas | IIgs ceiling | meas | DOS ceiling | meas |
|---|---|---|---|---|---|---|---|---|
| Sprite draw, arbitrary x | ~2,235-2,750 (pre-shifted movem RMW) | 585 aligned / far less unaligned | ~3,600-4,300 (blitter cookie-cut; CPU-compiled ~1,350) | 903 aligned only | 4,300 aligned / 2,490 odd (compiled stores) | 907 | ~11,000 | 6,094 |
| Sprite save or restore | ~5,300 (move.l window) | 703/553 | ~6,300-7,400 (A->D blit) | 567/553 | ~2,520 (MVN) | 543/568 | ~14,500-18,000 | 8,964/5,744 |
| Tile paste 8x8 | ~12,700-15,500 | 1,574 | ~10,700 | 2,253 | ~5,830 | 1,803 | ~57,000 | 9,454 |
| 40-tile row repaint | 352-880 | -- | ~316 | -- | ~190 | -- | ~1,900 | -- |
| Present (native answer) | page flip ~free + dirty bands (full copy ~53/s) | 56 | page flip ~free (8 copper pokes; full blit ~110/s) | 362* | dirty bands (full PEI 20-29/s; real HW ~14-32) | 68* | dirty bands (real ISA full blast 10-31 fps!) | 354* |
*Present measurement artifacts found: Amiga/DOS measured presents
EXCEED their physical full-copy ceilings because UBER's timed present
loop never re-dirties the stage -- after the first copy it measures the
dirty-union idle early-out, not a copy. IIgs 68 is the known SEI
inflation. The gameFrame workload row (below) fixes this by dirtying
every call.
Headline: the wrapper tax is universal and dominates -- tile paste runs
3-6x (up to ~10x ST, ~90% overhead DOS) below hand-coded ceilings on
EVERY port with cores already at parity; IIgs C glue measured at
~800-4,000 cycles per call (jlDrawPixel = 820 cycles for a 1-byte op).
Sprite ceilings are 2.5-4x above current aligned numbers (ST via
movem long-RMW + all 16 phases; Amiga via the BLITTER, which also
frees the CPU -- its compiled-CPU path caps at ~1,350).
### Item 2 RESULT -- alignment-cliff code truth (supersedes all memory)
SPRITE_SHIFT_INDEX (spriteInternal.h:24-30): Amiga x&7, ST
(x&7)?2:((x>>3)&1), chunky (IIgs/DOS) x&1. Emitters:
| Port | DRAW compiled | SAVE/RESTORE compiled | Fallback at NOT_COMPILED |
|---|---|---|---|
| IIgs | shifts 0+1 = EVERY x | shifts 0+1 = every x | (n/a -- no cliff) |
| DOS | shifts 0+1 = EVERY x | shifts 0+1 = every x | (n/a -- no cliff) |
| ST | 0,1 only (x%8==0) | NEVER (stubs) | draw: byte-wide shifted c2p walker (hal.c:1815+); save/restore: asm byte copy when x%8==0 else per-pixel pair walker |
| Amiga | shift 0 ONLY (x%8==0) | NEVER (stubs) | draw: shifted c2p walker (hal.c:1491); save/restore: plane-major copy when x%8==0 else pair walker |
So the cliff is 68k-ONLY: 7/8 x positions run walkers on ST/Amiga, and
jlSpriteSaveAndDraw's combined fast path NEVER fires on 68k (SAVE never
compiled). IIgs/DOS need nothing in Phase 1.
Phase-1 design constraints discovered: (a) ST's shift-2 bucket cannot
hold compiled code -- ST needs SPRITE_SHIFT_INDEX changed to x&7 (a
dispatcher-contract change) plus emitter support; (b) routineOffsets
are uint16_t so one sprite's compiled bytes must stay < 64KB -- 8 DRAW
variants of a mixed 32x32 (~8-16KB each) blow it; needs selective
emission or offset-scheme change (16x16 sprites fit fine); (c) the
jlSpriteRestoreUnder gate accepts only copyBytes == bytesPerRow or +1
(spriteCompile.c:547-552) -- planar shifted saves record +4, so the
gate must widen or 7/8 alignments stay interpreted even after emitters
land; (d) stale doc: sprite.h:32-40 contradicts spriteInternal.h:16-23
(fix during Phase 1); (e) uber.c:972 comment claims Amiga has 8
variants -- aspirational, false today.
### Item 3 -- workload rows [IN PROGRESS]
Four rows appended AFTER the surfaceMarkDirtyRect timeOp (cumulative-
hash safety: correctness checks clear the stage first, so the frozen 45
stay bit-identical; Phase-7 precedent):
- "jlSpriteDraw unaligned" -- x=71,y=120 (odd AND x%8==7: worst case on
all four ports simultaneously).
- "jlSpriteDraw sweep16" -- all 16 x phases (208..223) inside ONE call
so the op is idempotent regardless of per-port iteration counts.
- "jlTilePaste map 10x5" -- 50 pastes of two SNAPPED patterned tiles
(tile pixels are platform-private; only snap round-trips portably).
- "gameFrame composite" -- 256x96 repaint + 16 HUD tiles + 3 sprite
saveAndDraw + 3 restores + present, net-idempotent per call; all
sprite x mod-16-aligned so this row isolates wrapper tax + present
(rows above own the alignment signal). Also fixes the present-row
artifact (dirties every call).
Golden contract goes 45 -> 49. Refreeze procedure: regression gate
first (each port: exactly 45 match + 4 extra vs OLD golden), then
cross-identity (49/49 IIgs vs each), only then freeze + regenerate
PERF.md.
Gate: ceilings documented (DONE above); new rows golden'd x4; existing
45 untouched.
## Phase 1 -- Kill the alignment cliff
All-shift compiled sprites everywhere. ST: emit shifts covering all
x%16 phases in spriteEmitInterleaved68k (pre-shifted plane bytes +
masks spanning byte halves/groups; the Amiga 8-variant planar emitter
is the proven template). IIgs/DOS: odd-x nibble-shifted DRAW variants
(chunky). Save/restore already widen via shift where applicable --
verify per port. Arena sizing: 8x DRAW variants (Amiga precedent:
8-32KB arena; re-check DEFAULT_CODEGEN_BYTES per port).
Gate: unaligned-sprite UBER rows reach ~parity with aligned rows on
every port; goldens hold.
## Phase 2 -- Strip the per-op tax
Plane-pointer caching (kill per-draw jlpSurfacePlanePtr x4), flattened
hot-op dispatch, inline dirty marks for the remaining hot ops (extend
the 2026-07-06 surfaceMarkDirtyRows inline that bought 2-5%), remove
redundant validation layers (core wrapper already proves s/bounds).
Gate: small-op rows (tileFill/Paste/Copy, sprite ops, fillRect small)
move measurably toward Phase-0 ceilings on all ports; goldens hold.
## Phase 3 -- Batch APIs
jlTileMapPaste (N tiles, one validation, one dirty union -- the
jlDrawText pattern generalized) + sprite batch draw/save/restore.
API shape needs Scott's sign-off before landing in public headers.
Gate: tilemap workload row approaches ceiling (per-tile overhead ~0);
goldens hold (new API rows get their own goldens).
## Phase 4 -- Port-native heavy weapons
Amiga: blitter cookie-cut sprite draw for larger-than-16x16 objects;
blitter tile/tilemap paste evaluation. ST: evaluate movem-based
row engines + restore-from-clean-buffer strategy for backgrounds.
IIgs: PEI-slam variants for batch paths where applicable.
Gate: per-op measurements vs ceilings; keep only what beats the
compiled-CPU path on the emulator (fillCircle lesson: no dead asm).
## Phase 5 -- Acceptance
Every workload row within ~1.5x of its Phase-0 ceiling per port, or a
documented cycle-proof that the remaining gap is structural (e.g. ST
interleaved-planar RMW). PERF.md gets a ceilings column. Update the
perf-directive memory with the outcome.
## Progress tracker
- [x] Phase 0 COMPLETE 2026-07-06. Ceilings + code-truth in this file
(above); four workload rows landed in uber.c and golden'd: regression
gate exactly 45 match + 4 extras on every port, cross-identity 49/49
x4 (bonus: sweep16 validated the ST/Amiga shifted c2p walkers pixel-
perfect at all 14 untested phases). Golden contract is now 49 lines.
BASELINE the later phases must move (ops/sec, millis clock):
jlSpriteDraw unaligned: ST 40 (5% of floor!) | Amiga 75 (9%) |
IIgs 842 | DOS 5115 -- vs aligned 607/903/902/6218 = the
15x/12x 68k cliff, Phase 1's gate.
jlSpriteDraw sweep16 (x16 = draws/sec): ST 32 | Amiga 80 |
IIgs 896 | DOS 5648 -- real arbitrary-x sprite rate.
jlTilePaste map 10x5 (x50 = tiles/sec): ST 1600 | Amiga 2300 |
IIgs 1750 | DOS 10000 -- Phase 2/3's gate (ceilings say
10-15k on 68k, 57k DOS).
gameFrame composite: ST 9 | Amiga 18 | IIgs 10 | DOS 18 fps --
the bottom-line number; the program ends when this is at/near
the port's refresh-limited ceiling or a documented structural
bound.
- [ ] Phase 1 (68k all-shift emitters + save/restore emitters;
constraints (a)-(e) in the Phase-0 item-2 section above)
- [ ] Phase 2
- [ ] Phase 3
- [ ] Phase 4
- [ ] Phase 5

102
PERF.md
View file

@ -24,10 +24,26 @@ is `jlFillCircle r=40` (74%); a whole-circle asm routine was tried and
did NOT help (per-span dispatch is not the cost -- the 8-way-symmetry
overlap fill dominates), so it stays on the C span walker for now.
**2026-07-06, NATIVE-PERF Phase 0:** four WORKLOAD rows were added (see
NATIVE-PERF-PLAN.md) and the goldens refrozen at **49 lines** after a
clean regression gate (45 match + exactly 4 extras per port) and full
4-port cross-identity. The new rows measure what games actually do, and
they expose the real problem the per-op rows hid: `jlSpriteDraw
unaligned` runs at **5% (ST) / 9% (Amiga)** of the IIgs floor -- a
15x/12x cliff vs the aligned row, because only x%8==0 draws are
compiled on the 68k ports (see the plan's code-truth table). The
`gameFrame composite` row is the bottom line: **ST 9 / Amiga 18 /
IIgs 10 / DOS 18 frames/sec** for a modest game frame. Bonus finding:
cross-identity of the sweep16 row validated the ST/Amiga shifted c2p
walkers as pixel-perfect at all 14 previously-untested x phases.
(Re-capture note: IIgs input/audio rows wobbled vs the prior MAME run
-- e.g. jlAudioFrameTick 50223 -> 27612 -- run-to-run MAME variance on
cheap ops; hashes are unaffected and those rows gate nothing.)
Correctness statement backing this table: all four ports produce
BYTE-IDENTICAL pixels on every measured op and every correctness
check -- 45/45 surface hashes match the frozen goldens in
tests/goldens/uber/ (34 timed ops + 11 hashed checks; the PASS/FAIL
check -- **49/49** surface hashes match the frozen goldens in
tests/goldens/uber/ (37 timed ops + 12 hashed checks; the PASS/FAIL
checks -- palette round-trip, PRNG golden sequence, sprite clip
round-trip, arena churn, sprite-from-surface -- pass everywhere).
The Phase 0-era divergences (#75 tilePasteMono three-way, #78 ST
@ -82,39 +98,43 @@ default cuts off the final checks).
| Op | IIgs (ops/sec) | Amiga (ops/sec, % of IIGS) | Atari ST (ops/sec, % of IIGS) | DOS (ops/sec, % of IIGS) |
| --- | --- | --- | --- | --- |
| jlSurfaceClear | 35 | 75 (214%) | 44 (126%) | 70 (200%) |
| jlPaletteSet | 1623 | 11503 (709%) | 5256 (324%) | 29474 (1816%) |
| jlScbSetRange | 163 | 3953 (2425%) | 2418 (1483%) | 8474 (5199%) |
| jlDrawPixel | 3423 | 5853 (171%) | **3322 (97%)** | 23524 (687%) |
| jlDrawLine H | 1143 | 1703 (149%) | 1341 (117%) | 5674 (496%) |
| jlDrawLine V | 99 | 269 (272%) | 120 (121%) | 494 (499%) |
| jlDrawLine diag | 42 | **40 (95%)** | 42 (100%) | 110 (262%) |
| jlDrawRect 100x100 | 90 | 203 (226%) | 100 (111%) | 399 (443%) |
| jlDrawCircle r=16 | 306 | **285 (93%)** | **178 (58%)** | 424 (139%) |
| jlDrawCircle r=80 | 70 | **63 (90%)** | **40 (57%)** | 96 (137%) |
| jlFillRect 16x16 | 603 | 1153 (191%) | **585 (97%)** | 2874 (477%) |
| jlFillRect 80x80 | 110 | 269 (245%) | 115 (105%) | 380 (345%) |
| jlFillRect 320x200 | 21 | 66 (314%) | 38 (181%) | 56 (267%) |
| jlFillCircle r=40 | 42 | **31 (74%)** | 75 (179%) | 153 (364%) |
| jlSamplePixel | 5223 | 7253 (139%) | **4862 (93%)** | 44244 (847%) |
| jlTileFill | 2043 | 2303 (113%) | **1516 (74%)** | 8894 (435%) |
| jlTileCopy | 1443 | 1853 (128%) | **1307 (91%)** | 8404 (582%) |
| jlTileCopyMasked | 624 | 953 (153%) | 677 (108%) | 3084 (494%) |
| jlTilePaste | 1803 | 2303 (128%) | **1544 (86%)** | 9454 (524%) |
| jlTileSnap | 2643 | 3503 (133%) | 2907 (110%) | 18624 (705%) |
| jlSpriteSaveUnder | 543 | 567 (104%) | 833 (153%) | 8964 (1651%) |
| jlSpriteDraw | 907 | 953 (105%) | **585 (64%)** | 6094 (672%) |
| jlSpriteRestoreUnder | 568 | **553 (97%)** | 655 (115%) | 5744 (1011%) |
| jlSpriteSaveAndDraw | 376 | **332 (88%)** | **318 (85%)** | 4204 (1118%) |
| jlStagePresent full | 68 | 359 (528%) | **56 (82%)** | 354 (521%) |
| jlInputPoll | 243 | 4003 (1647%) | 1425 (586%) | 3084 (1269%) |
| jlKeyDown | 12303 | 39753 (323%) | 22826 (186%) | 76514 (622%) |
| jlKeyPressed | 14043 | 38003 (271%) | 22826 (163%) | 74064 (527%) |
| jlMouseX | 30123 | 96703 (321%) | 59354 (197%) | 153864 (511%) |
| joeyJoyConnected | 12303 | 39303 (319%) | 22283 (181%) | 77144 (627%) |
| jlAudioFrameTick | 50223 | 56503 (113%) | **11724 (23%)** | 58664 (117%) |
| jlAudioIsPlayingMod | 13503 | 56403 (418%) | 29870 (221%) | 127334 (943%) |
| surfaceMarkDirtyRect (via jlFillRect 32x32) | 323 | 853 (264%) | 376 (116%) | 1474 (456%) |
| jlSurfaceClear | 33 | 75 (227%) | 44 (133%) | 66 (200%) |
| jlPaletteSet | 1561 | 11503 (737%) | 5256 (337%) | 29809 (1910%) |
| jlScbSetRange | 163 | 3953 (2425%) | 2418 (1483%) | 8495 (5212%) |
| jlDrawPixel | 3179 | 5853 (184%) | 3384 (106%) | 23757 (747%) |
| jlDrawLine H | 1142 | 1703 (149%) | 1341 (117%) | 5708 (500%) |
| jlDrawLine V | 99 | 269 (272%) | 132 (133%) | 470 (475%) |
| jlDrawLine diag | 42 | **40 (95%)** | 43 (102%) | 109 (260%) |
| jlDrawRect 100x100 | 89 | 203 (228%) | 108 (121%) | 377 (424%) |
| jlDrawCircle r=16 | 303 | **285 (94%)** | **184 (61%)** | 449 (148%) |
| jlDrawCircle r=80 | 70 | **63 (90%)** | **42 (60%)** | 98 (140%) |
| jlFillRect 16x16 | 605 | 1153 (191%) | 610 (101%) | 3013 (498%) |
| jlFillRect 80x80 | 110 | 269 (245%) | 120 (109%) | 414 (376%) |
| jlFillRect 320x200 | 21 | 66 (314%) | 40 (190%) | 58 (276%) |
| jlFillCircle r=40 | 42 | **31 (74%)** | 77 (183%) | 156 (371%) |
| jlSamplePixel | 4815 | 7253 (151%) | 4862 (101%) | 46397 (964%) |
| jlTileFill | 1981 | 2303 (116%) | **1603 (81%)** | 9313 (470%) |
| jlTileCopy | 1441 | 1853 (129%) | **1341 (93%)** | 8764 (608%) |
| jlTileCopyMasked | 623 | 953 (153%) | 689 (111%) | 3147 (505%) |
| jlTilePaste | 1741 | 2303 (132%) | **1574 (90%)** | 9806 (563%) |
| jlTileSnap | 2520 | 3503 (139%) | 2907 (115%) | 19247 (764%) |
| jlSpriteSaveUnder | 545 | 567 (104%) | 849 (156%) | 9229 (1693%) |
| jlSpriteDraw | 902 | 953 (106%) | **607 (67%)** | 6218 (689%) |
| jlSpriteRestoreUnder | 566 | **553 (98%)** | 689 (122%) | 5933 (1048%) |
| jlSpriteSaveAndDraw | 376 | **332 (88%)** | **328 (87%)** | 4271 (1136%) |
| jlStagePresent full | 67 | 359 (536%) | **55 (82%)** | 360 (537%) |
| jlInputPoll | 229 | 4003 (1748%) | 1400 (611%) | 3134 (1369%) |
| jlKeyDown | 10191 | 39753 (390%) | 22403 (220%) | 77800 (763%) |
| jlKeyPressed | 11432 | 38003 (332%) | 22344 (195%) | 74977 (656%) |
| jlMouseX | 20138 | 97703 (485%) | 58314 (290%) | 155140 (770%) |
| joeyJoyConnected | 10191 | 38903 (382%) | 21870 (215%) | 77819 (764%) |
| jlAudioFrameTick | 27612 | 56453 (204%) | **11732 (42%)** | 59162 (214%) |
| jlAudioIsPlayingMod | 11029 | 56503 (512%) | 29870 (271%) | 127794 (1159%) |
| surfaceMarkDirtyRect (via jlFillRect 32x32) | 323 | 853 (264%) | 389 (120%) | 1478 (458%) |
| jlSpriteDraw unaligned | 842 | **75 (9%)** | **40 (5%)** | 5115 (607%) |
| jlSpriteDraw sweep16 | 56 | **5 (9%)** | **2 (4%)** | 353 (630%) |
| jlTilePaste map 10x5 | 35 | 46 (131%) | **32 (91%)** | 200 (571%) |
| gameFrame composite | 10 | 18 (180%) | **9 (90%)** | 18 (180%) |
> **IIgs full-screen ceiling (~29 ops/sec).** A full-screen op moves
> 32000 bytes = 16000 word-stores x 6 cyc (STA long,X / PEI, both
@ -143,11 +163,15 @@ default cuts off the final checks).
constraint, no blitter allowed (STF baseline). The IIgs circle-outline
case is a known structural loss (3-register 65816 vs 16-register 68000
Bresenham; see feedback memory). With IIgs sprites now compiled, a
68k sprite gap re-opened: ST jlSpriteDraw 64%, ST jlSpriteSaveAndDraw
85%, ST jlTileFill 74%, and Amiga jlSpriteRestoreUnder 97% +
68k sprite gap re-opened: ST jlSpriteDraw 67%, ST jlSpriteSaveAndDraw
87%, ST jlTileFill 77%, and Amiga jlSpriteRestoreUnder 97% +
jlSpriteSaveAndDraw 88% remain below the IIgs floor (they were masked
while the IIgs interpreted; ST jlSpriteRestoreUnder is now 115%, above
floor, after the clock fix). The ST jlSpriteDraw case was investigated
while the IIgs interpreted; ST jlSpriteRestoreUnder is now 119%, above
floor, after the clock fix). A 2026-07-06 shared fix -- inlining the
per-row widen in surfaceMarkDirtyRows (removing an 8x function call in
every multi-row stage op's dirty mark) -- lifted all ST multi-row ops
~2-5% (tileFill 1516->1574, spriteDraw 585->607, tileCopy 1307->1366,
fillRect16 to 100%), the ST/Amiga counterpart to the IIgs asm marker. The ST jlSpriteDraw case was investigated
2026-07-06 and is ARCHITECTURAL, the same root as the ST circle gap:
DRAW is already compiled (JIT, shifts 0/1), but the word-interleaved
planar layout forces `move.b #imm,(d16,An)` (~18 cyc) per plane byte,

View file

@ -117,6 +117,18 @@ static unsigned char gBackupBytes[256];
static jlTileT gTileScratch;
// Phase 0 workload rows (NATIVE-PERF-PLAN.md item 3): patterned tiles
// seeded via draw+snap (tile pixels are platform-private; only a snap
// round-trips portably) and dedicated gameFrame sprite backups so the
// correctness-check gBackup state stays untouched.
static jlTileT gTileMapA;
static jlTileT gTileMapB;
#define UBER_FRAME_SPRITES 3
static jlSpriteBackupT gFrameBackups[UBER_FRAME_SPRITES];
static unsigned char gFrameBackupBytes[UBER_FRAME_SPRITES][256];
// Current timed-op number (1-based); mirrored into the mailbox. Lives
// up here because runForFrames re-writes it every loop pass: the SHR
@ -302,6 +314,106 @@ static void op_surfaceMarkDirty(void) { /* jlDrawPixel already marks; use fill i
jlFillRect(gStage, 0, 0, 32, 32, 0); }
// ----- Phase 0 workload ops (NATIVE-PERF-PLAN.md item 3) -----
// Worst-case unaligned x on every port at once: odd -> IIgs/DOS
// compiled shift-1 (widened RMW row); x % 8 == 7 -> ST shift index 2
// (never compiled, interpreted jlpSpriteDrawPlanes) and Amiga shift 7
// (only shift 0 compiled) with the maximal 7-bit spill across three
// plane bytes per row. Phase 1's all-shift emitters must pull this row
// to ~parity with the aligned jlSpriteDraw row.
#define UBER_UNALIGNED_X 71
#define UBER_UNALIGNED_Y 120
static void op_spriteDrawUnaligned(void) { jlSpriteDraw(gStage, gSprite, UBER_UNALIGNED_X, UBER_UNALIGNED_Y); }
// All 16 x phases in ONE call so the op is idempotent: per-port
// iteration counts and the 16-call unrolled batch would otherwise
// leave a port-dependent final x and a port-dependent hash. 208..223
// covers each Amiga shift twice, both ST compiled shifts (208, 216)
// plus all 14 interpreter phases, and 8 even + 8 odd IIgs/DOS draws.
// Reported ops/sec is SWEEPS per second: multiply by 16 for draws/sec.
#define UBER_SWEEP_X0 208
#define UBER_SWEEP_Y 120
static void op_spriteDrawSweep(void) {
int16_t x;
for (x = UBER_SWEEP_X0; x < (int16_t)(UBER_SWEEP_X0 + 16); x++) {
jlSpriteDraw(gStage, gSprite, x, UBER_SWEEP_Y);
}
}
// 50 single-tile pastes = the per-call wrapper tax paid 50 times; the
// Phase 3 jlTileMapPaste batch API must beat this row by roughly the
// per-call overhead fraction. Fixed checker of two snapped tiles.
#define UBER_TILEMAP_X0 12
#define UBER_TILEMAP_Y0 12
#define UBER_TILEMAP_W 10
#define UBER_TILEMAP_H 5
static void op_tileMapPaste(void) {
uint8_t tx;
uint8_t ty;
for (ty = 0; ty < UBER_TILEMAP_H; ty++) {
for (tx = 0; tx < UBER_TILEMAP_W; tx++) {
if (((tx + ty) & 1u) == 0u) {
jlTilePaste(gStage, (uint8_t)(UBER_TILEMAP_X0 + tx), (uint8_t)(UBER_TILEMAP_Y0 + ty), &gTileMapA);
} else {
jlTilePaste(gStage, (uint8_t)(UBER_TILEMAP_X0 + tx), (uint8_t)(UBER_TILEMAP_Y0 + ty), &gTileMapB);
}
}
}
}
// One realistic game frame: repaint a play region, paste a HUD tile
// row, save+draw three sprites, restore them in reverse, present.
// The fill runs FIRST in the same call, so the saves always capture
// UBER_FRAME_BG and the surface is net-identical after every call --
// the post-window hash is iteration-count independent. All sprite x
// are mod-16-aligned (compiled shift 0 on every port): this row
// isolates the per-call wrapper tax + present; the rows above own the
// alignment signal. Presenting a re-dirtied stage every call also
// fixes the present-row artifact (the timed jlStagePresent row goes
// idle after its first copy).
#define UBER_FRAME_RX 32
#define UBER_FRAME_RY 64
#define UBER_FRAME_RW 256
#define UBER_FRAME_RH 96
#define UBER_FRAME_BG 6
#define UBER_FRAME_TILES 16
#define UBER_FRAME_TILE_TX 4
#define UBER_FRAME_TILE_TY 8
static const int16_t gFrameSpriteX[UBER_FRAME_SPRITES] = { 48, 144, 240 };
static const int16_t gFrameSpriteY[UBER_FRAME_SPRITES] = { 80, 96, 112 };
static void op_gameFrame(void) {
int16_t i;
uint8_t t;
jlFillRect(gStage, UBER_FRAME_RX, UBER_FRAME_RY, UBER_FRAME_RW, UBER_FRAME_RH, UBER_FRAME_BG);
for (t = 0; t < UBER_FRAME_TILES; t++) {
if ((t & 1u) == 0u) {
jlTilePaste(gStage, (uint8_t)(UBER_FRAME_TILE_TX + t), UBER_FRAME_TILE_TY, &gTileMapA);
} else {
jlTilePaste(gStage, (uint8_t)(UBER_FRAME_TILE_TX + t), UBER_FRAME_TILE_TY, &gTileMapB);
}
}
for (i = 0; i < UBER_FRAME_SPRITES; i++) {
jlSpriteSaveAndDraw(gStage, gSprite, gFrameSpriteX[i], gFrameSpriteY[i], &gFrameBackups[i]);
}
for (i = UBER_FRAME_SPRITES - 1; i >= 0; i--) {
jlSpriteRestoreUnder(gStage, &gFrameBackups[i]);
}
jlStagePresent();
}
// ----- Build the ball sprite procedurally -----
#define BALL_TILES_X 2
@ -896,6 +1008,31 @@ static void __attribute__((noinline)) runAllTests(void) {
// Surface mark dirty (via jlFillRect's mark step).
timeOp("surfaceMarkDirtyRect (via jlFillRect 32x32)", op_surfaceMarkDirty);
// ----- Phase 0 workload rows (NATIVE-PERF-PLAN.md item 3). Appended
// last on purpose: timed hashes are cumulative and the correctness
// checks clear the stage first, so the frozen lines above stay
// bit-identical (Phase-7 golden-extension precedent).
timeOp("jlSpriteDraw unaligned", op_spriteDrawUnaligned);
timeOp("jlSpriteDraw sweep16", op_spriteDrawSweep);
// Seed two patterned tiles via portable draws + snap. jlTileT.pixels
// is platform-private (plane bytes on ST/Amiga), so hand-written
// bytes would render differently per port; only a snap round-trips.
jlFillRect(gStage, 0, 72, 4, 4, 3);
jlFillRect(gStage, 4, 72, 4, 4, 5);
jlFillRect(gStage, 0, 76, 4, 4, 5);
jlFillRect(gStage, 4, 76, 4, 4, 3);
jlTileSnap(gStage, 0, 9, &gTileMapA);
jlFillRect(gStage, 8, 72, 8, 8, 9);
jlDrawLine(gStage, 8, 72, 15, 79, 1);
jlTileSnap(gStage, 1, 9, &gTileMapB);
gFrameBackups[0].bytes = gFrameBackupBytes[0];
gFrameBackups[1].bytes = gFrameBackupBytes[1];
gFrameBackups[2].bytes = gFrameBackupBytes[2];
timeOp("jlTilePaste map 10x5", op_tileMapPaste);
timeOp("gameFrame composite", op_gameFrame);
jlLogF("UBER: ----- end -----\n");
}

View file

@ -1368,15 +1368,11 @@ void jlpTileFill(jlSurfaceT *s, uint8_t bx, uint8_t by, uint8_t colorIndex) {
uint16_t halfMask;
uint8_t *gp;
if (s->portData == NULL) {
jlpGenericTileFill(s, bx, by, colorIndex);
return;
}
if (s == NULL) {
return;
}
// Core jlTileFill already proved s != NULL and clipped bx/by; only
// the non-planar (offscreen, no portData) fallback needs handling.
pd = (StPlanarT *)s->portData;
if (pd == NULL) {
jlpGenericTileFill(s, bx, by, colorIndex);
return;
}
group = (uint16_t)((uint16_t)bx >> 1);

View file

@ -43,19 +43,9 @@ bool gStagePaletteDirty = true;
// ----- Internal helpers (alphabetical) -----
// widenRow serves only the non-IIgs surfaceMarkDirtyRows loop; the
// IIgs multi-row path is the asm marker and the single-row path is
// inlined by the surfaceMarkDirtyRect macro (surfaceInternal.h).
#ifndef JOEYLIB_PLATFORM_IIGS
static void widenRow(int16_t y, uint8_t minWord, uint8_t maxWord) {
if (minWord < gStageMinWord[y]) {
gStageMinWord[y] = minWord;
}
if (maxWord > gStageMaxWord[y]) {
gStageMaxWord[y] = maxWord;
}
}
#endif
// (surfaceMarkDirtyRows inlines the per-row widen with walking pointers
// -- see below. The single-row widen is inlined by the surfaceMarkDirtyRect
// macro, and the IIgs multi-row path is the asm marker.)
// ----- Public API (alphabetical) -----
@ -243,10 +233,27 @@ void surfaceMarkDirtyAll(const jlSurfaceT *s) {
// iigsMarkDirtyRowsInner instead.
#ifndef JOEYLIB_PLATFORM_IIGS
void surfaceMarkDirtyRows(uint16_t y, uint16_t yEnd, uint8_t minWord, uint8_t maxWord) {
uint16_t row;
uint8_t *minPtr;
uint8_t *maxPtr;
uint8_t *minEnd;
for (row = y; row < yEnd; row++) {
widenRow((int16_t)row, minWord, maxWord);
// Straight-line inlined widen (no per-row helper call) with walking
// pointers, so a multi-row stage op -- tile fill/paste/copy, sprite
// draw, fillRect -- pays one tight loop instead of yEnd-y function
// calls. This is the ST/Amiga counterpart to the IIgs asm marker;
// the 8-row tile mark was ~a third of jlTileFill's cost.
minPtr = &gStageMinWord[y];
maxPtr = &gStageMaxWord[y];
minEnd = &gStageMinWord[yEnd];
while (minPtr < minEnd) {
if (minWord < *minPtr) {
*minPtr = minWord;
}
if (maxWord > *maxPtr) {
*maxPtr = maxWord;
}
minPtr++;
maxPtr++;
}
}
#endif

View file

@ -12,69 +12,151 @@ UBER: ----- begin -----
UBER: jlSurfaceClear: 33 iters / 22 frames = 75 ops/sec | hash=428CEE42
UBER: jlPaletteSet: 2145 iters / 16 frames = 6703 ops/sec | hash=5267FFB1
UBER-CLK: jlSurfaceClear: frame=75 millis=75 ops/sec (440 ms)
UBER: jlScbSetRange: 1233 iters / 16 frames = 3853 ops/sec | hash=5267FFB1
UBER: jlPaletteSet: 3681 iters / 16 frames = 11503 ops/sec | hash=5267FFB1
UBER: jlDrawPixel: 1361 iters / 16 frames = 4253 ops/sec | hash=75D75161
UBER-CLK: jlPaletteSet: frame=11503 millis=11503 ops/sec (320 ms)
UBER: jlDrawLine H: 513 iters / 16 frames = 1603 ops/sec | hash=1E97E361
UBER: jlScbSetRange: 1265 iters / 16 frames = 3953 ops/sec | hash=5267FFB1
UBER: jlDrawLine V: 49 iters / 16 frames = 153 ops/sec | hash=A0474D91
UBER-CLK: jlScbSetRange: frame=3953 millis=3953 ops/sec (320 ms)
UBER: jlDrawPixel: 1873 iters / 16 frames = 5853 ops/sec | hash=75D75161
UBER-CLK: jlDrawPixel: frame=5853 millis=5853 ops/sec (320 ms)
UBER: jlDrawLine H: 545 iters / 16 frames = 1703 ops/sec | hash=1E97E361
UBER-CLK: jlDrawLine H: frame=1703 millis=1703 ops/sec (320 ms)
UBER: jlDrawLine V: 97 iters / 18 frames = 269 ops/sec | hash=A0474D91
UBER-CLK: jlDrawLine V: frame=269 millis=269 ops/sec (360 ms)
UBER: jlDrawLine diag: 13 iters / 16 frames = 40 ops/sec | hash=69471D91
UBER: jlDrawRect 100x100: 49 iters / 19 frames = 128 ops/sec | hash=5CAFF471
UBER-CLK: jlDrawLine diag: frame=40 millis=40 ops/sec (320 ms)
UBER: jlDrawRect 100x100: 65 iters / 16 frames = 203 ops/sec | hash=5CAFF471
UBER-CLK: jlDrawRect 100x100: frame=203 millis=203 ops/sec (320 ms)
UBER: jlDrawCircle r=16: 97 iters / 17 frames = 285 ops/sec | hash=7F1F5531
UBER-CLK: jlDrawCircle r=16: frame=285 millis=285 ops/sec (340 ms)
UBER: jlDrawCircle r=80: 33 iters / 26 frames = 63 ops/sec | hash=B249C9AB
UBER: jlFillRect 16x16: 193 iters / 17 frames = 567 ops/sec | hash=F4BD4B0B
UBER-CLK: jlDrawCircle r=80: frame=63 millis=63 ops/sec (520 ms)
UBER: jlFillRect 80x80: 33 iters / 23 frames = 71 ops/sec | hash=7C952E5F
UBER: jlFillRect 16x16: 369 iters / 16 frames = 1153 ops/sec | hash=F4BD4B0B
UBER: jlFillRect 320x200: 33 iters / 24 frames = 68 ops/sec | hash=6467AFB1
UBER-CLK: jlFillRect 16x16: frame=1153 millis=1153 ops/sec (320 ms)
UBER: jlFillRect 80x80: 97 iters / 18 frames = 269 ops/sec | hash=7C952E5F
UBER-CLK: jlFillRect 80x80: frame=269 millis=269 ops/sec (360 ms)
UBER: jlFillRect 320x200: 33 iters / 25 frames = 66 ops/sec | hash=6467AFB1
UBER-CLK: jlFillRect 320x200: frame=66 millis=66 ops/sec (500 ms)
UBER: jlFillCircle r=40: 10 iters / 16 frames = 31 ops/sec | hash=6467AFB1
UBER-CLK: jlFillCircle r=40: frame=31 millis=31 ops/sec (320 ms)
UBER: jlSamplePixel: 2321 iters / 16 frames = 7253 ops/sec | hash=6467AFB1
UBER: jlTileFill: 721 iters / 16 frames = 2253 ops/sec | hash=6467AFB1
UBER-CLK: jlSamplePixel: frame=7253 millis=7253 ops/sec (320 ms)
UBER: jlTileFill: 737 iters / 16 frames = 2303 ops/sec | hash=6467AFB1
UBER-CLK: jlTileFill: frame=2303 millis=2303 ops/sec (320 ms)
UBER: jlTileCopy: 593 iters / 16 frames = 1853 ops/sec | hash=6467AFB1
UBER-CLK: jlTileCopy: frame=1853 millis=1853 ops/sec (320 ms)
UBER: jlTileCopyMasked: 305 iters / 16 frames = 953 ops/sec | hash=6467AFB1
UBER-CLK: jlTileCopyMasked: frame=953 millis=953 ops/sec (320 ms)
UBER: jlTilePaste: 737 iters / 16 frames = 2303 ops/sec | hash=6467AFB1
UBER: jlTileSnap: 1137 iters / 16 frames = 3553 ops/sec | hash=6467AFB1
UBER-CLK: jlTilePaste: frame=2303 millis=2303 ops/sec (320 ms)
UBER: jlSpriteSaveUnder: 177 iters / 16 frames = 553 ops/sec | hash=CA673FB1
UBER: jlTileSnap: 1121 iters / 16 frames = 3503 ops/sec | hash=6467AFB1
UBER-CLK: jlTileSnap: frame=3503 millis=3503 ops/sec (320 ms)
UBER: jlSpriteSaveUnder: 193 iters / 17 frames = 567 ops/sec | hash=CA673FB1
UBER-CLK: jlSpriteSaveUnder: frame=567 millis=567 ops/sec (340 ms)
UBER: jlSpriteDraw: 305 iters / 16 frames = 953 ops/sec | hash=82B9646B
UBER-CLK: jlSpriteDraw: frame=953 millis=953 ops/sec (320 ms)
UBER: jlSpriteRestoreUnder: 177 iters / 16 frames = 553 ops/sec | hash=CA673FB1
UBER: jlSpriteSaveAndDraw: 113 iters / 16 frames = 353 ops/sec | hash=82B9646B
UBER-CLK: jlSpriteRestoreUnder: frame=553 millis=553 ops/sec (320 ms)
UBER: jlStagePresent full: 105 iters / 16 frames = 328 ops/sec | hash=82B9646B
UBER: jlSpriteSaveAndDraw: 113 iters / 17 frames = 332 ops/sec | hash=82B9646B
UBER-CLK: jlSpriteSaveAndDraw: frame=332 millis=332 ops/sec (340 ms)
UBER: jlStagePresent full: 115 iters / 16 frames = 359 ops/sec | hash=82B9646B
UBER-CLK: jlStagePresent full: frame=359 millis=359 ops/sec (320 ms)
UBER: jlInputPoll: 1281 iters / 16 frames = 4003 ops/sec | hash=82B9646B
UBER: jlKeyDown: 12737 iters / 16 frames = 39803 ops/sec | hash=82B9646B
UBER-CLK: jlInputPoll: frame=4003 millis=4003 ops/sec (320 ms)
UBER: jlKeyDown: 12721 iters / 16 frames = 39753 ops/sec | hash=82B9646B
UBER-CLK: jlKeyDown: frame=39753 millis=39753 ops/sec (320 ms)
UBER: jlKeyPressed: 12161 iters / 16 frames = 38003 ops/sec | hash=82B9646B
UBER-CLK: jlKeyPressed: frame=38003 millis=38003 ops/sec (320 ms)
UBER: jlMouseX: 31265 iters / 16 frames = 97703 ops/sec | hash=82B9646B
UBER: joeyJoyConnected: 12465 iters / 16 frames = 38953 ops/sec | hash=82B9646B
UBER-CLK: jlMouseX: frame=97703 millis=97703 ops/sec (320 ms)
UBER: jlAudioFrameTick: 18241 iters / 16 frames = 57003 ops/sec | hash=82B9646B
UBER: joeyJoyConnected: 12449 iters / 16 frames = 38903 ops/sec | hash=82B9646B
UBER: jlAudioIsPlayingMod: 17857 iters / 16 frames = 55803 ops/sec | hash=82B9646B
UBER-CLK: joeyJoyConnected: frame=38903 millis=38903 ops/sec (320 ms)
UBER: surfaceMarkDirtyRect (via jlFillRect 32x32): 113 iters / 16 frames = 353 ops/sec | hash=D2B9E46B
UBER: jlAudioFrameTick: 18065 iters / 16 frames = 56453 ops/sec | hash=82B9646B
UBER-CLK: jlAudioFrameTick: frame=56453 millis=56453 ops/sec (320 ms)
UBER: jlAudioIsPlayingMod: 18081 iters / 16 frames = 56503 ops/sec | hash=82B9646B
UBER-CLK: jlAudioIsPlayingMod: frame=56503 millis=56503 ops/sec (320 ms)
UBER: surfaceMarkDirtyRect (via jlFillRect 32x32): 273 iters / 16 frames = 853 ops/sec | hash=D2B9E46B
UBER-CLK: surfaceMarkDirtyRect (via jlFillRect 32x32): frame=853 millis=853 ops/sec (320 ms)
UBER: jlSpriteDraw unaligned: 33 iters / 22 frames = 75 ops/sec | hash=69CEBB34
UBER-CLK: jlSpriteDraw unaligned: frame=75 millis=75 ops/sec (440 ms)
UBER: jlSpriteDraw sweep16: 2 iters / 19 frames = 5 ops/sec | hash=24E7E0C9
UBER-CLK: jlSpriteDraw sweep16: frame=5 millis=5 ops/sec (380 ms)
UBER: jlTilePaste map 10x5: 15 iters / 16 frames = 46 ops/sec | hash=92E7B0C9
UBER-CLK: jlTilePaste map 10x5: frame=46 millis=46 ops/sec (320 ms)
UBER: gameFrame composite: 6 iters / 16 frames = 18 ops/sec | hash=55B9EC6B
UBER-CLK: gameFrame composite: frame=18 millis=18 ops/sec (320 ms)
UBER: ----- end -----
@ -116,5 +198,7 @@ UBER-CHK: floodFillBounded: hash=EF6B6F51
UBER-CHK: ----- end -----
UBER: total wall time: 145820 ms (7291 frames @ 50 Hz)
UBER: total wall time: 165280 ms (8264 frames @ 50 Hz)
UBER: press any key to exit

View file

@ -6,71 +6,153 @@ UBER: showcase cells: 0=pixels 1=lineH 2=lineV 3=diag 4=rect 5=fillRect 6=circle
UBER: ----- begin -----
UBER: jlSurfaceClear: 12 iters / 16 frames = 37 ops/sec | hash=428CEE42
UBER: jlSurfaceClear: 12 iters / 16 frames = 44 ops/sec | hash=428CEE42
UBER: jlPaletteSet: 1009 iters / 16 frames = 3153 ops/sec | hash=5267FFB1
UBER-CLK: jlSurfaceClear: frame=45 millis=44 ops/sec (270 ms)
UBER: jlScbSetRange: 641 iters / 16 frames = 2003 ops/sec | hash=5267FFB1
UBER: jlPaletteSet: 1393 iters / 16 frames = 5256 ops/sec | hash=5267FFB1
UBER: jlDrawPixel: 721 iters / 16 frames = 2253 ops/sec | hash=75D75161
UBER-CLK: jlPaletteSet: frame=5223 millis=5256 ops/sec (265 ms)
UBER: jlDrawLine H: 369 iters / 16 frames = 1153 ops/sec | hash=1E97E361
UBER: jlScbSetRange: 641 iters / 16 frames = 2418 ops/sec | hash=5267FFB1
UBER: jlDrawLine V: 33 iters / 16 frames = 103 ops/sec | hash=A0474D91
UBER-CLK: jlScbSetRange: frame=2403 millis=2418 ops/sec (265 ms)
UBER: jlDrawLine diag: 12 iters / 16 frames = 37 ops/sec | hash=69471D91
UBER: jlDrawPixel: 897 iters / 16 frames = 3384 ops/sec | hash=75D75161
UBER: jlDrawRect 100x100: 33 iters / 19 frames = 86 ops/sec | hash=5CAFF471
UBER-CLK: jlDrawPixel: frame=3363 millis=3384 ops/sec (265 ms)
UBER: jlDrawCircle r=16: 49 iters / 16 frames = 153 ops/sec | hash=7F1F5531
UBER: jlDrawLine H: 369 iters / 16 frames = 1341 ops/sec | hash=1E97E361
UBER: jlDrawCircle r=80: 11 iters / 16 frames = 34 ops/sec | hash=B249C9AB
UBER-CLK: jlDrawLine H: frame=1383 millis=1341 ops/sec (275 ms)
UBER: jlFillRect 16x16: 177 iters / 17 frames = 520 ops/sec | hash=F4BD4B0B
UBER: jlDrawLine V: 49 iters / 22 frames = 132 ops/sec | hash=A0474D91
UBER: jlFillRect 80x80: 33 iters / 16 frames = 103 ops/sec | hash=7C952E5F
UBER-CLK: jlDrawLine V: frame=133 millis=132 ops/sec (370 ms)
UBER: jlFillRect 320x200: 11 iters / 17 frames = 32 ops/sec | hash=6467AFB1
UBER: jlDrawLine diag: 12 iters / 16 frames = 43 ops/sec | hash=69471D91
UBER: jlFillCircle r=40: 33 iters / 26 frames = 63 ops/sec | hash=6467AFB1
UBER-CLK: jlDrawLine diag: frame=45 millis=43 ops/sec (275 ms)
UBER: jlSamplePixel: 1313 iters / 16 frames = 4103 ops/sec | hash=6467AFB1
UBER: jlDrawRect 100x100: 33 iters / 18 frames = 108 ops/sec | hash=5CAFF471
UBER: jlTileFill: 417 iters / 16 frames = 1303 ops/sec | hash=6467AFB1
UBER-CLK: jlDrawRect 100x100: frame=110 millis=108 ops/sec (305 ms)
UBER: jlTileCopy: 353 iters / 16 frames = 1103 ops/sec | hash=6467AFB1
UBER: jlDrawCircle r=16: 49 iters / 16 frames = 184 ops/sec | hash=7F1F5531
UBER: jlTileCopyMasked: 193 iters / 17 frames = 567 ops/sec | hash=6467AFB1
UBER-CLK: jlDrawCircle r=16: frame=183 millis=184 ops/sec (265 ms)
UBER: jlTilePaste: 417 iters / 16 frames = 1303 ops/sec | hash=6467AFB1
UBER: jlDrawCircle r=80: 12 iters / 17 frames = 42 ops/sec | hash=B249C9AB
UBER: jlTileSnap: 785 iters / 16 frames = 2453 ops/sec | hash=6467AFB1
UBER-CLK: jlDrawCircle r=80: frame=42 millis=42 ops/sec (285 ms)
UBER: jlSpriteSaveUnder: 225 iters / 16 frames = 703 ops/sec | hash=CA673FB1
UBER: jlFillRect 16x16: 177 iters / 17 frames = 610 ops/sec | hash=F4BD4B0B
UBER: jlSpriteDraw: 161 iters / 16 frames = 503 ops/sec | hash=82B9646B
UBER-CLK: jlFillRect 16x16: frame=624 millis=610 ops/sec (290 ms)
UBER: jlSpriteRestoreUnder: 177 iters / 16 frames = 553 ops/sec | hash=CA673FB1
UBER: jlFillRect 80x80: 33 iters / 16 frames = 120 ops/sec | hash=7C952E5F
UBER: jlSpriteSaveAndDraw: 97 iters / 18 frames = 269 ops/sec | hash=82B9646B
UBER-CLK: jlFillRect 80x80: frame=123 millis=120 ops/sec (275 ms)
UBER: jlStagePresent full: 15 iters / 16 frames = 46 ops/sec | hash=82B9646B
UBER: jlFillRect 320x200: 11 iters / 16 frames = 40 ops/sec | hash=6467AFB1
UBER: jlInputPoll: 385 iters / 16 frames = 1203 ops/sec | hash=82B9646B
UBER-CLK: jlFillRect 320x200: frame=41 millis=40 ops/sec (275 ms)
UBER: jlKeyDown: 6049 iters / 16 frames = 18903 ops/sec | hash=82B9646B
UBER: jlFillCircle r=40: 33 iters / 25 frames = 77 ops/sec | hash=6467AFB1
UBER: jlKeyPressed: 6049 iters / 16 frames = 18903 ops/sec | hash=82B9646B
UBER-CLK: jlFillCircle r=40: frame=79 millis=77 ops/sec (425 ms)
UBER: jlMouseX: 15745 iters / 16 frames = 49203 ops/sec | hash=82B9646B
UBER: jlSamplePixel: 1313 iters / 16 frames = 4862 ops/sec | hash=6467AFB1
UBER: joeyJoyConnected: 5921 iters / 16 frames = 18503 ops/sec | hash=82B9646B
UBER-CLK: jlSamplePixel: frame=4923 millis=4862 ops/sec (270 ms)
UBER: jlAudioFrameTick: 3152 iters / 16 frames = 9850 ops/sec | hash=82B9646B
UBER: jlTileFill: 433 iters / 16 frames = 1603 ops/sec | hash=6467AFB1
UBER: jlAudioIsPlayingMod: 8065 iters / 16 frames = 25203 ops/sec | hash=82B9646B
UBER-CLK: jlTileFill: frame=1623 millis=1603 ops/sec (270 ms)
UBER: surfaceMarkDirtyRect (via jlFillRect 32x32): 113 iters / 17 frames = 332 ops/sec | hash=D2B9E46B
UBER: jlTileCopy: 369 iters / 16 frames = 1341 ops/sec | hash=6467AFB1
UBER-CLK: jlTileCopy: frame=1383 millis=1341 ops/sec (275 ms)
UBER: jlTileCopyMasked: 193 iters / 16 frames = 689 ops/sec | hash=6467AFB1
UBER-CLK: jlTileCopyMasked: frame=723 millis=689 ops/sec (280 ms)
UBER: jlTilePaste: 433 iters / 16 frames = 1574 ops/sec | hash=6467AFB1
UBER-CLK: jlTilePaste: frame=1623 millis=1574 ops/sec (275 ms)
UBER: jlTileSnap: 785 iters / 16 frames = 2907 ops/sec | hash=6467AFB1
UBER-CLK: jlTileSnap: frame=2943 millis=2907 ops/sec (270 ms)
UBER: jlSpriteSaveUnder: 225 iters / 16 frames = 849 ops/sec | hash=CA673FB1
UBER-CLK: jlSpriteSaveUnder: frame=843 millis=849 ops/sec (265 ms)
UBER: jlSpriteDraw: 161 iters / 16 frames = 607 ops/sec | hash=82B9646B
UBER-CLK: jlSpriteDraw: frame=603 millis=607 ops/sec (265 ms)
UBER: jlSpriteRestoreUnder: 193 iters / 17 frames = 689 ops/sec | hash=CA673FB1
UBER-CLK: jlSpriteRestoreUnder: frame=681 millis=689 ops/sec (280 ms)
UBER: jlSpriteSaveAndDraw: 97 iters / 17 frames = 328 ops/sec | hash=82B9646B
UBER-CLK: jlSpriteSaveAndDraw: frame=342 millis=328 ops/sec (295 ms)
UBER: jlStagePresent full: 15 iters / 16 frames = 55 ops/sec | hash=82B9646B
UBER-CLK: jlStagePresent full: frame=56 millis=55 ops/sec (270 ms)
UBER: jlInputPoll: 385 iters / 16 frames = 1400 ops/sec | hash=82B9646B
UBER-CLK: jlInputPoll: frame=1443 millis=1400 ops/sec (275 ms)
UBER: jlKeyDown: 6049 iters / 16 frames = 22403 ops/sec | hash=82B9646B
UBER-CLK: jlKeyDown: frame=22683 millis=22403 ops/sec (270 ms)
UBER: jlKeyPressed: 6033 iters / 16 frames = 22344 ops/sec | hash=82B9646B
UBER-CLK: jlKeyPressed: frame=22623 millis=22344 ops/sec (270 ms)
UBER: jlMouseX: 15745 iters / 16 frames = 58314 ops/sec | hash=82B9646B
UBER-CLK: jlMouseX: frame=59043 millis=58314 ops/sec (270 ms)
UBER: joeyJoyConnected: 5905 iters / 16 frames = 21870 ops/sec | hash=82B9646B
UBER-CLK: joeyJoyConnected: frame=22143 millis=21870 ops/sec (270 ms)
UBER: jlAudioFrameTick: 3109 iters / 16 frames = 11732 ops/sec | hash=82B9646B
UBER-CLK: jlAudioFrameTick: frame=11658 millis=11732 ops/sec (265 ms)
UBER: jlAudioIsPlayingMod: 8065 iters / 16 frames = 29870 ops/sec | hash=82B9646B
UBER-CLK: jlAudioIsPlayingMod: frame=30243 millis=29870 ops/sec (270 ms)
UBER: surfaceMarkDirtyRect (via jlFillRect 32x32): 113 iters / 17 frames = 389 ops/sec | hash=D2B9E46B
UBER-CLK: surfaceMarkDirtyRect (via jlFillRect 32x32): frame=398 millis=389 ops/sec (290 ms)
UBER: jlSpriteDraw unaligned: 11 iters / 16 frames = 40 ops/sec | hash=69CEBB34
UBER-CLK: jlSpriteDraw unaligned: frame=41 millis=40 ops/sec (270 ms)
UBER: jlSpriteDraw sweep16: 1 iters / 21 frames = 2 ops/sec | hash=24E7E0C9
UBER-CLK: jlSpriteDraw sweep16: frame=2 millis=2 ops/sec (350 ms)
UBER: jlTilePaste map 10x5: 9 iters / 17 frames = 32 ops/sec | hash=92E7B0C9
UBER-CLK: jlTilePaste map 10x5: frame=31 millis=32 ops/sec (280 ms)
UBER: gameFrame composite: 3 iters / 19 frames = 9 ops/sec | hash=55B9EC6B
UBER-CLK: gameFrame composite: frame=9 millis=9 ops/sec (325 ms)
UBER: ----- end -----
@ -112,7 +194,7 @@ UBER-CHK: floodFillBounded: hash=EF6B6F51
UBER-CHK: ----- end -----
UBER: total wall time: 302060 ms (15103 frames @ 50 Hz)
UBER: total wall time: 289833 ms (17390 frames @ 60 Hz)
UBER: press any key to exit

View file

@ -6,71 +6,153 @@ UBER: showcase cells: 0=pixels 1=lineH 2=lineV 3=diag 4=rect 5=fillRect 6=circle
UBER: ----- begin -----
UBER: jlSurfaceClear: 16 iters / 17 frames = 65 ops/sec | hash=428CEE42
UBER: jlSurfaceClear: 16 iters / 16 frames = 66 ops/sec | hash=428CEE42
UBER: jlPaletteSet: 3505 iters / 16 frames = 15334 ops/sec | hash=5267FFB1
UBER-CLK: jlSurfaceClear: frame=70 millis=66 ops/sec (239 ms)
UBER: jlScbSetRange: 1889 iters / 16 frames = 8264 ops/sec | hash=5267FFB1
UBER: jlPaletteSet: 6737 iters / 16 frames = 29809 ops/sec | hash=5267FFB1
UBER: jlDrawPixel: 3985 iters / 16 frames = 17434 ops/sec | hash=75D75161
UBER-CLK: jlPaletteSet: frame=29474 millis=29809 ops/sec (226 ms)
UBER: jlDrawLine H: 1329 iters / 16 frames = 5814 ops/sec | hash=1E97E361
UBER: jlScbSetRange: 1937 iters / 16 frames = 8495 ops/sec | hash=5267FFB1
UBER: jlDrawLine V: 81 iters / 16 frames = 354 ops/sec | hash=A0474D91
UBER-CLK: jlScbSetRange: frame=8474 millis=8495 ops/sec (228 ms)
UBER: jlDrawLine diag: 33 iters / 24 frames = 96 ops/sec | hash=69471D91
UBER: jlDrawPixel: 5393 iters / 16 frames = 23757 ops/sec | hash=75D75161
UBER: jlDrawRect 100x100: 81 iters / 16 frames = 354 ops/sec | hash=5CAFF471
UBER-CLK: jlDrawPixel: frame=23594 millis=23757 ops/sec (227 ms)
UBER: jlDrawCircle r=16: 85 iters / 16 frames = 371 ops/sec | hash=7F1F5531
UBER: jlDrawLine H: 1313 iters / 16 frames = 5708 ops/sec | hash=1E97E361
UBER: jlDrawCircle r=80: 19 iters / 16 frames = 83 ops/sec | hash=B249C9AB
UBER-CLK: jlDrawLine H: frame=5744 millis=5708 ops/sec (230 ms)
UBER: jlFillRect 16x16: 609 iters / 16 frames = 2664 ops/sec | hash=F4BD4B0B
UBER: jlDrawLine V: 113 iters / 16 frames = 470 ops/sec | hash=A0474D91
UBER: jlFillRect 80x80: 81 iters / 16 frames = 354 ops/sec | hash=7C952E5F
UBER-CLK: jlDrawLine V: frame=494 millis=470 ops/sec (240 ms)
UBER: jlFillRect 320x200: 13 iters / 16 frames = 56 ops/sec | hash=6467AFB1
UBER: jlDrawLine diag: 33 iters / 21 frames = 109 ops/sec | hash=69471D91
UBER: jlFillCircle r=40: 29 iters / 16 frames = 126 ops/sec | hash=6467AFB1
UBER-CLK: jlDrawLine diag: frame=110 millis=109 ops/sec (301 ms)
UBER: jlSamplePixel: 8321 iters / 16 frames = 36404 ops/sec | hash=6467AFB1
UBER: jlDrawRect 100x100: 82 iters / 16 frames = 377 ops/sec | hash=5CAFF471
UBER: jlTileFill: 2081 iters / 16 frames = 9104 ops/sec | hash=6467AFB1
UBER-CLK: jlDrawRect 100x100: frame=358 millis=377 ops/sec (217 ms)
UBER: jlTileCopy: 1569 iters / 16 frames = 6864 ops/sec | hash=6467AFB1
UBER: jlDrawCircle r=16: 97 iters / 16 frames = 449 ops/sec | hash=7F1F5531
UBER: jlTileCopyMasked: 545 iters / 16 frames = 2384 ops/sec | hash=6467AFB1
UBER-CLK: jlDrawCircle r=16: frame=424 millis=449 ops/sec (216 ms)
UBER: jlTilePaste: 1825 iters / 16 frames = 7984 ops/sec | hash=6467AFB1
UBER: jlDrawCircle r=80: 22 iters / 16 frames = 98 ops/sec | hash=B249C9AB
UBER: jlTileSnap: 2993 iters / 16 frames = 13094 ops/sec | hash=6467AFB1
UBER-CLK: jlDrawCircle r=80: frame=96 millis=98 ops/sec (223 ms)
UBER: jlSpriteSaveUnder: 1937 iters / 16 frames = 8474 ops/sec | hash=CA673FB1
UBER: jlFillRect 16x16: 657 iters / 16 frames = 3013 ops/sec | hash=F4BD4B0B
UBER: jlSpriteDraw: 1393 iters / 16 frames = 6094 ops/sec | hash=82B9646B
UBER-CLK: jlFillRect 16x16: frame=2874 millis=3013 ops/sec (218 ms)
UBER: jlSpriteRestoreUnder: 1297 iters / 16 frames = 5674 ops/sec | hash=CA673FB1
UBER: jlFillRect 80x80: 97 iters / 17 frames = 414 ops/sec | hash=7C952E5F
UBER: jlSpriteSaveAndDraw: 961 iters / 16 frames = 4204 ops/sec | hash=82B9646B
UBER-CLK: jlFillRect 80x80: frame=399 millis=414 ops/sec (234 ms)
UBER: jlStagePresent full: 81 iters / 16 frames = 354 ops/sec | hash=82B9646B
UBER: jlFillRect 320x200: 13 iters / 16 frames = 58 ops/sec | hash=6467AFB1
UBER: jlInputPoll: 705 iters / 16 frames = 3084 ops/sec | hash=82B9646B
UBER-CLK: jlFillRect 320x200: frame=56 millis=58 ops/sec (221 ms)
UBER: jlKeyDown: 17441 iters / 16 frames = 76304 ops/sec | hash=82B9646B
UBER: jlFillCircle r=40: 35 iters / 16 frames = 156 ops/sec | hash=6467AFB1
UBER: jlKeyPressed: 16897 iters / 16 frames = 73924 ops/sec | hash=82B9646B
UBER-CLK: jlFillCircle r=40: frame=153 millis=156 ops/sec (223 ms)
UBER: jlMouseX: 35105 iters / 16 frames = 153584 ops/sec | hash=82B9646B
UBER: jlSamplePixel: 10161 iters / 16 frames = 46397 ops/sec | hash=6467AFB1
UBER: joeyJoyConnected: 17601 iters / 16 frames = 77004 ops/sec | hash=82B9646B
UBER-CLK: jlSamplePixel: frame=44454 millis=46397 ops/sec (219 ms)
UBER: jlAudioFrameTick: 13377 iters / 16 frames = 58524 ops/sec | hash=82B9646B
UBER: jlTileFill: 2049 iters / 16 frames = 9313 ops/sec | hash=6467AFB1
UBER: jlAudioIsPlayingMod: 29041 iters / 16 frames = 127054 ops/sec | hash=82B9646B
UBER-CLK: jlTileFill: frame=8964 millis=9313 ops/sec (220 ms)
UBER: surfaceMarkDirtyRect (via jlFillRect 32x32): 305 iters / 16 frames = 1334 ops/sec | hash=D2B9E46B
UBER: jlTileCopy: 1937 iters / 16 frames = 8764 ops/sec | hash=6467AFB1
UBER-CLK: jlTileCopy: frame=8474 millis=8764 ops/sec (221 ms)
UBER: jlTileCopyMasked: 705 iters / 16 frames = 3147 ops/sec | hash=6467AFB1
UBER-CLK: jlTileCopyMasked: frame=3084 millis=3147 ops/sec (224 ms)
UBER: jlTilePaste: 2177 iters / 16 frames = 9806 ops/sec | hash=6467AFB1
UBER-CLK: jlTilePaste: frame=9524 millis=9806 ops/sec (222 ms)
UBER: jlTileSnap: 4273 iters / 16 frames = 19247 ops/sec | hash=6467AFB1
UBER-CLK: jlTileSnap: frame=18694 millis=19247 ops/sec (222 ms)
UBER: jlSpriteSaveUnder: 2049 iters / 16 frames = 9229 ops/sec | hash=CA673FB1
UBER-CLK: jlSpriteSaveUnder: frame=8964 millis=9229 ops/sec (222 ms)
UBER: jlSpriteDraw: 1393 iters / 16 frames = 6218 ops/sec | hash=82B9646B
UBER-CLK: jlSpriteDraw: frame=6094 millis=6218 ops/sec (224 ms)
UBER: jlSpriteRestoreUnder: 1329 iters / 16 frames = 5933 ops/sec | hash=CA673FB1
UBER-CLK: jlSpriteRestoreUnder: frame=5814 millis=5933 ops/sec (224 ms)
UBER: jlSpriteSaveAndDraw: 961 iters / 16 frames = 4271 ops/sec | hash=82B9646B
UBER-CLK: jlSpriteSaveAndDraw: frame=4204 millis=4271 ops/sec (225 ms)
UBER: jlStagePresent full: 81 iters / 16 frames = 360 ops/sec | hash=82B9646B
UBER-CLK: jlStagePresent full: frame=354 millis=360 ops/sec (225 ms)
UBER: jlInputPoll: 721 iters / 16 frames = 3134 ops/sec | hash=82B9646B
UBER-CLK: jlInputPoll: frame=3154 millis=3134 ops/sec (230 ms)
UBER: jlKeyDown: 17505 iters / 16 frames = 77800 ops/sec | hash=82B9646B
UBER-CLK: jlKeyDown: frame=76584 millis=77800 ops/sec (225 ms)
UBER: jlKeyPressed: 16945 iters / 16 frames = 74977 ops/sec | hash=82B9646B
UBER-CLK: jlKeyPressed: frame=74134 millis=74977 ops/sec (226 ms)
UBER: jlMouseX: 35217 iters / 16 frames = 155140 ops/sec | hash=82B9646B
UBER-CLK: jlMouseX: frame=154074 millis=155140 ops/sec (227 ms)
UBER: joeyJoyConnected: 17665 iters / 16 frames = 77819 ops/sec | hash=82B9646B
UBER-CLK: joeyJoyConnected: frame=77284 millis=77819 ops/sec (227 ms)
UBER: jlAudioFrameTick: 13489 iters / 16 frames = 59162 ops/sec | hash=82B9646B
UBER-CLK: jlAudioFrameTick: frame=59014 millis=59162 ops/sec (228 ms)
UBER: jlAudioIsPlayingMod: 29265 iters / 16 frames = 127794 ops/sec | hash=82B9646B
UBER-CLK: jlAudioIsPlayingMod: frame=128034 millis=127794 ops/sec (229 ms)
UBER: surfaceMarkDirtyRect (via jlFillRect 32x32): 337 iters / 16 frames = 1478 ops/sec | hash=D2B9E46B
UBER-CLK: surfaceMarkDirtyRect (via jlFillRect 32x32): frame=1474 millis=1478 ops/sec (228 ms)
UBER: jlSpriteDraw unaligned: 1105 iters / 16 frames = 5115 ops/sec | hash=69CEBB34
UBER-CLK: jlSpriteDraw unaligned: frame=4834 millis=5115 ops/sec (216 ms)
UBER: jlSpriteDraw sweep16: 77 iters / 16 frames = 353 ops/sec | hash=24E7E0C9
UBER-CLK: jlSpriteDraw sweep16: frame=336 millis=353 ops/sec (218 ms)
UBER: jlTilePaste map 10x5: 44 iters / 16 frames = 200 ops/sec | hash=92E7B0C9
UBER-CLK: jlTilePaste map 10x5: frame=192 millis=200 ops/sec (220 ms)
UBER: gameFrame composite: 5 iters / 19 frames = 18 ops/sec | hash=55B9EC6B
UBER-CLK: gameFrame composite: frame=18 millis=18 ops/sec (270 ms)
UBER: ----- end -----
@ -112,7 +194,7 @@ UBER-CHK: floodFillBounded: hash=EF6B6F51
UBER-CHK: ----- end -----
UBER: total wall time: 20928 ms (1465 frames @ 70 Hz)
UBER: total wall time: 23142 ms (1620 frames @ 70 Hz)
UBER: press any key to exit

View file

@ -1,41 +1,81 @@
UBER: jlSpriteCompile failed
UBER: jlSpriteCompile: 1 call in <= 1 frame
UBER: audioInit OK
UBER: showcase cells: 0=pixels 1=lineH 2=lineV 3=diag 4=rect 5=fillRect 6=circle 7=fillCircle 8=tiles 9=sprite 10=flood 11=scene
UBER: ----- begin -----
UBER: jlSurfaceClear: 10 iters / 17 frames = 35 ops/sec | hash=428CEE42
UBER: jlPaletteSet: 385 iters / 16 frames = 1443 ops/sec | hash=5267FFB1
UBER: jlSurfaceClear: 9 iters / 16 frames = 33 ops/sec | hash=428CEE42
UBER-CLK: jlSurfaceClear: frame=33 millis=33 ops/sec (266 ms)
UBER: jlPaletteSet: 417 iters / 16 frames = 1561 ops/sec | hash=5267FFB1
UBER-CLK: jlPaletteSet: frame=1563 millis=1561 ops/sec (267 ms)
UBER: jlScbSetRange: 49 iters / 18 frames = 163 ops/sec | hash=5267FFB1
UBER: jlDrawPixel: 865 iters / 16 frames = 3243 ops/sec | hash=75D75161
UBER: jlDrawLine H: 273 iters / 16 frames = 1023 ops/sec | hash=1E97E361
UBER-CLK: jlScbSetRange: frame=163 millis=163 ops/sec (300 ms)
UBER: jlDrawPixel: 849 iters / 16 frames = 3179 ops/sec | hash=75D75161
UBER-CLK: jlDrawPixel: frame=3183 millis=3179 ops/sec (267 ms)
UBER: jlDrawLine H: 305 iters / 16 frames = 1142 ops/sec | hash=1E97E361
UBER-CLK: jlDrawLine H: frame=1143 millis=1142 ops/sec (267 ms)
UBER: jlDrawLine V: 33 iters / 20 frames = 99 ops/sec | hash=A0474D91
UBER-CLK: jlDrawLine V: frame=99 millis=99 ops/sec (333 ms)
UBER: jlDrawLine diag: 12 iters / 17 frames = 42 ops/sec | hash=69471D91
UBER: jlDrawRect 100x100: 33 iters / 23 frames = 86 ops/sec | hash=5CAFF471
UBER-CLK: jlDrawLine diag: frame=42 millis=42 ops/sec (284 ms)
UBER: jlDrawRect 100x100: 33 iters / 22 frames = 89 ops/sec | hash=5CAFF471
UBER-CLK: jlDrawRect 100x100: frame=90 millis=89 ops/sec (367 ms)
UBER: jlDrawCircle r=16: 81 iters / 16 frames = 303 ops/sec | hash=7F1F5531
UBER-CLK: jlDrawCircle r=16: frame=303 millis=303 ops/sec (267 ms)
UBER: jlDrawCircle r=80: 33 iters / 28 frames = 70 ops/sec | hash=B249C9AB
UBER: jlFillRect 16x16: 145 iters / 17 frames = 511 ops/sec | hash=F4BD4B0B
UBER-CLK: jlDrawCircle r=80: frame=70 millis=70 ops/sec (466 ms)
UBER: jlFillRect 16x16: 161 iters / 16 frames = 605 ops/sec | hash=F4BD4B0B
UBER-CLK: jlFillRect 16x16: frame=603 millis=605 ops/sec (266 ms)
UBER: jlFillRect 80x80: 33 iters / 18 frames = 110 ops/sec | hash=7C952E5F
UBER-CLK: jlFillRect 80x80: frame=110 millis=110 ops/sec (300 ms)
UBER: jlFillRect 320x200: 6 iters / 17 frames = 21 ops/sec | hash=6467AFB1
UBER-CLK: jlFillRect 320x200: frame=21 millis=21 ops/sec (284 ms)
UBER: jlFillCircle r=40: 12 iters / 17 frames = 42 ops/sec | hash=6467AFB1
UBER: jlSamplePixel: 1313 iters / 16 frames = 4923 ops/sec | hash=6467AFB1
UBER: jlTileFill: 433 iters / 16 frames = 1623 ops/sec | hash=6467AFB1
UBER: jlTileCopy: 337 iters / 16 frames = 1263 ops/sec | hash=6467AFB1
UBER: jlTileCopyMasked: 161 iters / 16 frames = 603 ops/sec | hash=6467AFB1
UBER: jlTilePaste: 417 iters / 16 frames = 1563 ops/sec | hash=6467AFB1
UBER: jlTileSnap: 705 iters / 16 frames = 2643 ops/sec | hash=6467AFB1
UBER: jlSpriteSaveUnder: 33 iters / 19 frames = 104 ops/sec | hash=CA673FB1
UBER: jlSpriteDraw: 5 iters / 16 frames = 18 ops/sec | hash=82B9646B
UBER: jlSpriteRestoreUnder: 33 iters / 18 frames = 110 ops/sec | hash=CA673FB1
UBER: jlSpriteSaveAndDraw: 5 iters / 19 frames = 15 ops/sec | hash=82B9646B
UBER: jlStagePresent full: 33 iters / 28 frames = 70 ops/sec | hash=82B9646B
UBER: jlInputPoll: 65 iters / 16 frames = 243 ops/sec | hash=82B9646B
UBER: jlKeyDown: 3281 iters / 16 frames = 12303 ops/sec | hash=82B9646B
UBER: jlKeyPressed: 3745 iters / 16 frames = 14043 ops/sec | hash=82B9646B
UBER: jlMouseX: 8033 iters / 16 frames = 30123 ops/sec | hash=82B9646B
UBER: joeyJoyConnected: 3281 iters / 16 frames = 12303 ops/sec | hash=82B9646B
UBER: jlAudioFrameTick: 13393 iters / 16 frames = 50223 ops/sec | hash=82B9646B
UBER: jlAudioIsPlayingMod: 3601 iters / 16 frames = 13503 ops/sec | hash=82B9646B
UBER: surfaceMarkDirtyRect (via jlFillRect 32x32): 81 iters / 16 frames = 303 ops/sec | hash=D2B9E46B
UBER-CLK: jlFillCircle r=40: frame=42 millis=42 ops/sec (283 ms)
UBER: jlSamplePixel: 1281 iters / 16 frames = 4815 ops/sec | hash=6467AFB1
UBER-CLK: jlSamplePixel: frame=4803 millis=4815 ops/sec (266 ms)
UBER: jlTileFill: 529 iters / 16 frames = 1981 ops/sec | hash=6467AFB1
UBER-CLK: jlTileFill: frame=1983 millis=1981 ops/sec (267 ms)
UBER: jlTileCopy: 385 iters / 16 frames = 1441 ops/sec | hash=6467AFB1
UBER-CLK: jlTileCopy: frame=1443 millis=1441 ops/sec (267 ms)
UBER: jlTileCopyMasked: 177 iters / 17 frames = 623 ops/sec | hash=6467AFB1
UBER-CLK: jlTileCopyMasked: frame=624 millis=623 ops/sec (284 ms)
UBER: jlTilePaste: 465 iters / 16 frames = 1741 ops/sec | hash=6467AFB1
UBER-CLK: jlTilePaste: frame=1743 millis=1741 ops/sec (267 ms)
UBER: jlTileSnap: 673 iters / 16 frames = 2520 ops/sec | hash=6467AFB1
UBER-CLK: jlTileSnap: frame=2523 millis=2520 ops/sec (267 ms)
UBER: jlSpriteSaveUnder: 145 iters / 16 frames = 545 ops/sec | hash=CA673FB1
UBER-CLK: jlSpriteSaveUnder: frame=543 millis=545 ops/sec (266 ms)
UBER: jlSpriteDraw: 241 iters / 16 frames = 902 ops/sec | hash=82B9646B
UBER-CLK: jlSpriteDraw: frame=903 millis=902 ops/sec (267 ms)
UBER: jlSpriteRestoreUnder: 161 iters / 17 frames = 566 ops/sec | hash=CA673FB1
UBER-CLK: jlSpriteRestoreUnder: frame=568 millis=566 ops/sec (284 ms)
UBER: jlSpriteSaveAndDraw: 113 iters / 18 frames = 376 ops/sec | hash=82B9646B
UBER-CLK: jlSpriteSaveAndDraw: frame=376 millis=376 ops/sec (300 ms)
UBER: jlStagePresent full: 18 iters / 16 frames = 67 ops/sec | hash=82B9646B
UBER-CLK: jlStagePresent full: frame=67 millis=67 ops/sec (266 ms)
UBER: jlInputPoll: 65 iters / 17 frames = 229 ops/sec | hash=82B9646B
UBER-CLK: jlInputPoll: frame=229 millis=229 ops/sec (283 ms)
UBER: jlKeyDown: 2721 iters / 16 frames = 10191 ops/sec | hash=82B9646B
UBER-CLK: jlKeyDown: frame=10203 millis=10191 ops/sec (267 ms)
UBER: jlKeyPressed: 3041 iters / 16 frames = 11432 ops/sec | hash=82B9646B
UBER-CLK: jlKeyPressed: frame=11403 millis=11432 ops/sec (266 ms)
UBER: jlMouseX: 5377 iters / 16 frames = 20138 ops/sec | hash=82B9646B
UBER-CLK: jlMouseX: frame=20163 millis=20138 ops/sec (267 ms)
UBER: joeyJoyConnected: 2721 iters / 16 frames = 10191 ops/sec | hash=82B9646B
UBER-CLK: joeyJoyConnected: frame=10203 millis=10191 ops/sec (267 ms)
UBER: jlAudioFrameTick: 7345 iters / 16 frames = 27612 ops/sec | hash=82B9646B
UBER-CLK: jlAudioFrameTick: frame=27543 millis=27612 ops/sec (266 ms)
UBER: jlAudioIsPlayingMod: 2945 iters / 16 frames = 11029 ops/sec | hash=82B9646B
UBER-CLK: jlAudioIsPlayingMod: frame=11043 millis=11029 ops/sec (267 ms)
UBER: surfaceMarkDirtyRect (via jlFillRect 32x32): 97 iters / 18 frames = 323 ops/sec | hash=D2B9E46B
UBER-CLK: surfaceMarkDirtyRect (via jlFillRect 32x32): frame=323 millis=323 ops/sec (300 ms)
UBER: jlSpriteDraw unaligned: 225 iters / 16 frames = 842 ops/sec | hash=69CEBB34
UBER-CLK: jlSpriteDraw unaligned: frame=843 millis=842 ops/sec (267 ms)
UBER: jlSpriteDraw sweep16: 15 iters / 16 frames = 56 ops/sec | hash=24E7E0C9
UBER-CLK: jlSpriteDraw sweep16: frame=56 millis=56 ops/sec (267 ms)
UBER: jlTilePaste map 10x5: 10 iters / 17 frames = 35 ops/sec | hash=92E7B0C9
UBER-CLK: jlTilePaste map 10x5: frame=35 millis=35 ops/sec (283 ms)
UBER: gameFrame composite: 3 iters / 18 frames = 10 ops/sec | hash=55B9EC6B
UBER-CLK: gameFrame composite: frame=10 millis=10 ops/sec (300 ms)
UBER: ----- end -----
UBER-CHK: ----- begin -----
UBER-CHK: edge-pixels: hash=5267FFB1
@ -54,9 +94,7 @@ UBER-CHK: arena-churn: PASS
UBER-CHK: sprite-from-surface: PASS
UBER-CHK: sprite-from-surface-draw: hash=5F4394C9
UBER-CHK: tilePasteMonoAll: hash=30C3A2C9
UBER-CHK: floodFillBounded: hash=EF6B6F51
UBER-CHK: ----- end -----
UBER: total wall time: 367016 ms (22021 frames @ 60 Hz)
UBER: total wall time: 419016 ms (25141 frames @ 60 Hz)
UBER: press any key to exit