Skip to content
Agentmart
Submit a tool

ios-performance-measurement

Procedure for confirming a performance fix actually worked, with a real number, instead of asserting improvement from reading code.

Skill by apexbymanish

IndexedMIT
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/apexbymanish-ios-performance-measurement

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Procedure for confirming a performance fix actually worked, with a real number, instead of asserting improvement from reading code. Use when asked to "make this faster", "why is this slow", "measure this", "profile this", or before/after a performance change needs proof it helped.

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/ios-performance-measurement

What's inside

Skill name
ios-performance-measurement
Description
Procedure for confirming a performance fix actually worked, with a real number, instead of asserting improvement from reading code. Use when asked to "make this faster", "why is this slow", "measure this", "profile this", or before/after a performance change needs proof it helped.
License
MIT
Instructions
296 lines in SKILL.md · view on GitHub

Files (1)

  • SKILL.md

SKILL.md (first lines)

# iOS Performance Measurement

Reading code can find a *plausible* cause. It cannot tell you whether
fixing that cause actually moved the number, or whether a completely
different layer was the real bottleneck. This procedure exists for the
gap between "this should be faster" and "this is faster, by this much."

Two rules govern everything below:

1. **Take the number before changing anything.** Change first and the
   only thing left to say afterward is "feels faster" — which is not a
   number and cannot be defended.
2. **The first guess is usually wrong.** Main-thread decoding and heavy
   layout are the guesses everyone reaches for first; they're the
   actual cause less than half the time in practice. Trust the
   measurement over the guess, and drop the guess the moment a
   measurement contradicts it — don't go looking for a reason the
   measurement must be wrong instead.

The full loop, in order: **REPRODUCE → BASELINE → MEASURE → CHANGE →
BUILD → TEST → MEASURE AGAIN → COMPARE → REPORT.** Skipping straight
from REPRODUCE to CHANGE is exactly what turns a real fix into an
unfalsifiable "should be faster now."

## REPRODUCE — pin down the reproduction before measuring anything

A before/after comparison is only valid if the same action happened
under the same conditions both times. Write these down first:

- Device and OS version — and whether it's a simulator or a physical
  device (see below; this materially changes what the numbers mean).
- Build configuration — Debug vs. Release. Release has optimizations
  Debug doesn't; a Debug-measured improvement can vanish or invert in
  Release.
- Data scale — how many list items, how many/how large images.
- The exact action sequence — launch → tap X → scroll N times.
- Cache state — cold (first launch) or warm (second+ launch).

**Simulator numbers are not device numbers.** A simulator runs on the
Mac's own CPU/GPU, so raw computation looks fast, I/O behaves
differently, and there is no thermal throttling, no real memory
pressure, and no real network latency to contend with.

| | Simulator | Physical device |
|---|---|---|
| Use for | quickly checking direction (better/worse) | **claiming an actual number** |
| Trustworthy for | relative comparison only | absolute values |
| Missing entirely | thermal state, memory pressure, low-end hardware | — |

Any number reported to the user should come from a physical device
where one is available. If only a simulator is available, say so
explicitly in the report rather than presenting the number as if it
were a device measurement.

**Only one simulator should be booted while timing anything.**
Simulators share the Mac's CPU/GPU, so a second one running in parallel
inflates every timing number (though not counts — request counts and
allocation counts don't drift with contention). Check before timing:

```sh
xcrun simctl list devices booted | grep -c Booted   # should be 1
```

Never run `xcrun simctl shutdown all`, `erase all`, or
`delete unavailable` to clear the field — those are global and can
destroy a simulator another session or another person on the same
Mac is actively using. Target a specific UDID instead.

## BASELINE — choose the one thing to measure, and say why

Trying to measure everything at once measures nothing usefully. Pick
the layer most likely to explain the complaint, and state the
reasoning before touching anything:

| Layer | What moves | Points here when |
|---|---|---|
| Launch | time to first frame, time to interactive | app-start work is piling up sequentially |
| Tap response (hang) | count and duration of stalls | tapped, and the response is late — main thread is held |
| Scroll (hitch) | dropped-frame count, overage per frame | scrolling/transitions stutter — render missed its budget |
| Network | request count, **duplicate requests**, response size/time | request count scales with the number of items on screen |
| Decoding | decode time, which thread it runs on | decoding is happening on the main thread |
| Main-thread occupancy | time held per event | any event handler exceeds ~16.7ms (60Hz frame budget) |
| Object churn | heavy objects created in a repeated path | formatters/regexes/encoders instantiated inside a loop |
| Memory | cache hit/miss, retained size after leaving a screen | memory doesn't come back down after navigating away |

If both hangs and hitches are plausible, capture both from the same
on-device trace and compare their totals, not just their counts — a
2:1 count ratio can hide an 8:1 duration ratio, and duration is what
tells you which layer to actually fix.

## BASELINE — prefer a path that needs no code before writing any

Check this table before adding a single line of instrumentation code —
several common questions are answerable with zero app changes:

| Question | Answer without touching the app |
|---|---|
| Request count, duplicates, response size/time | An HTTP proxy on the device/simulator |
| Hangs, hitches, launch time, thermal state | An on-device Instruments Time Profiler trace |
| Actual retained memory after leaving a screen | An on-device memory sample via Instruments Allocations/Leaks, or the VM Tracker instrument for a page-level view of resident memory |
| Pure algorithmic/logic time, in-process without launching Instruments | `XCTMetric` inside a test (`measure(metrics:)`), or `os_signpost` intervals viewed in Instruments' Points of Interest track |
| Custom, code-level timing markers you want to see on a real device's timeline | `os_signpost` — cheaper and more precise than `print`-based timing, and it shows up directly in an Instruments trace |

Instrumentation code is only justified for what's left after this
table: screen-entry latency tied to a specific line, which thread a
decode runs on, or a count of objects created in a specific hot path.
Code you add for measurement has to be removed later — every line
you avoid adding is a line you don't have to remember to remove.

## BASELINE — if you do add instrumentation, keep it removable

- **Never let it survive into a release build.** Wrap it so the string
  work itself doesn't happen outside debug builds:

```swift
enum Measure {
    /// The label is @autoclosure so a Release build never even builds the string.
    static func mark(_ label: @autoclosure () -> String) {
        #if DEBUG

From apexbymanish/claude-ai-agents-ios, MIT.

More from apexbymanish/claude-ai-agents-ios

Signals

Stars
0
Forks
0
Open issues
0
Last commit (this folder)
Aug 28, 2026 (2 months ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from apexbymanish

Cite this page

ios-performance-measurement skill. Agent Mart. https://agentmart.dev/skills/apexbymanish-ios-performance-measurement (last updated 2026-10-24)