> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mobster.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Launch time, memory and hangs

> Read the launch time, memory and hangs of every check, and fail one that goes over its budget.

Every run on a simulator takes four numbers while it checks your flow. They land in `perf` in `results.json`, in the HTML report, in the pull request comment and in JUnit (properties `perf.launchMs`, `perf.memoryMb` and `perf.hangs`).

## Set a budget

Set limits with `budget` in a check file ([the keys](https://docs.mobster.dev/checks.md#the-check-file)):

```yaml theme={"theme":"css-variables"}
budget:
  launch_ms: 2500
  memory_mb: 400
  hangs: 0
```

A run over a limit fails with class `budget_exceeded` and says which number and by how much. A limit on a number the run couldn't take, such as `memory_mb` on an iPhone, ends the run `needs_review` with class `budget_unmeasured`. Mobster never passes a budget it can't check.

## Read what a check measures

| Number | How Mobster takes it |
| - | - |
| Cold launch | The time from the `simctl launch` call to the first accessibility read of the app's own screen that the next read agrees with: `perf.launch.interactiveMs`. It reads every 0.1 s, so it has that resolution plus the time of one read. `foregroundMs` is the time until WebDriverAgent names your app as the app in front |
| Memory | The app's resident memory, from `ps` on its process when it is in front, every 500 ms after that, and once more at the verdict read. `peakMb` is the largest sample and `p95Mb` the nearest-rank 95th percentile. Resident size is larger than the footprint Xcode shows, and it includes shared frameworks |
| Hangs | The lines `Hang detected: 0.52s` in the app's own log of 250 ms or longer. `count` and `longestMs` |
| CPU | The largest `ps` CPU share of the process, in `memory.cpuPeakPct`. One busy core is about 100 |

What Mobster doesn't measure is in `perf.notMeasured`, so a missing number says why:

* **First frame.** A simulator writes no log line that marks the app's first frame, so `launch` has no `firstFrameMs`. Cold launch ends at the first stable screen, which comes after the first frame.
* **Dropped frames.** A simulator exposes no Core Animation commit times, and MetricKit isn't available in one.
* **Memory on an iPhone.** A phone run takes the two launch times and the hang count, and `memory` is `null`.
* **Hangs on a simulator.** A simulator may not log hangs at all. A count of 0 means no hang line appeared.

## Watch the numbers over time

`mobster test --history` keeps the numbers per run and marks the last run against the median of the last 10 passes before it. `↑` is 20% more launch time or memory, or more hangs than the median. `↓` is 20% less, and `→` is in between. It marks nothing until 3 earlier passes have the number.&#x20;

```text theme={"theme":"css-variables"}
stable  Feed loads  on iPhone 17 Pro  ✓✓✓✓✓✓✓  100% of 7 runs, flake score 0.00
    Last run: launch 1,329 ms →, memory 278 MB →, hangs 0 →.
```

The marker flags a trend and never fails a check. Only `budget` fails one. `--history --json` adds `perfLatest` (the last run's numbers) and `perf` (each number's marker, latest value, baseline median and run count) to every row.&#x20;


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.