> For the complete documentation index, see [llms.txt](https://tyrix.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tyrix.gitbook.io/docs/script-resources/tyrix-frames/performance.md).

# Performance

Two claims, and why they hold.

## 0.00 ms in resmon, including with photos on screen

Displaying a photo costs **no per-frame script time at all**. The image is bound directly to the canvas material, so once it is set the game draws it and the script does nothing. There is no draw loop anywhere in this resource.

With photos visible, the only work happening is a streaming tick — 250 ms when canvases are near, 1000 ms otherwise — and an activation check gated to 500 ms. Both iterate only what is nearby. That is microseconds, which resmon reports as 0.00.

Away from canvases the client holds an empty registry and the tick does no work at all.

## Cost does not grow with how many canvases exist

A server with 10,000 placed canvases costs a client the same as one with 50. Only local density matters.

### Joins and restarts

Join payload is set by local density, not by the size of the table. Restarting the resource on a full server does not produce a bandwidth spike, because no client receives more than its own window.

## Props

Canvas props are **client-local, non-networked and frozen**. They consume no entity budget and no network budget. Each client spawns its own copy from replicated data and deletes it when out of range, with hysteresis so a canvas on the boundary cannot spawn/despawn repeatedly.

## Photo renderers

A canvas becomes a live renderer only when it has a photo, is spawned, is within `Config.RenderDistance`, and wins one of the `Config.MaxActiveDuis` slots. Slots go to the nearest canvases and are pooled by resolution, so walking through a gallery reuses browser instances rather than churning them. Idle ones are reclaimed after 90 seconds.

Past the cap, extra canvases show the blank placeholder until a slot frees. That is the intended graceful degradation - a photo-dense room loses some photos at distance rather than stuttering.

{% hint style="warning" %}
**One canvas per model renders at a time.** Textures bind per model, and each size ships 10 variants; the server hands neighbouring canvases different variants. If more than 10 same-size canvases end up clustered within render distance, some must share a model and the furthest will mirror or show blank. Mix sizes, or space clusters out - 7 sizes × 10 variants is 70 distinct models.
{% endhint %}

## Server

| Path         | Behaviour                                                                                   |
| ------------ | ------------------------------------------------------------------------------------------- |
| Registry     | Loaded once at start, held in memory. No SQL on any hot path.                               |
| Writes       | Only on mutation, which is rare per player.                                                 |
| Broadcasts   | Proportional to nearby players, not connected players.                                      |
| Rate limits  | Every client-reachable callback is limited per player, sliding 60-second window.            |
| Image probes | Concurrency-capped with a short result cache, so the shared HTTP client can't be saturated. |
| Discord      | Queued and drained at a safe rate, with drop-oldest under flood.                            |

## Tuning for photo-dense builds

If your server has rooms with a dozen canvases in them:

| Setting                 | Try                                                                                         |
| ----------------------- | ------------------------------------------------------------------------------------------- |
| `Config.MaxActiveDuis`  | Raise from 8. Each renderer is \~30–60 MB, so go up in small steps and watch client memory. |
| `Config.RenderDistance` | Lower it so fewer canvases compete for slots at once.                                       |
| Canvas sizes            | Mix them. Same-size clusters exhaust the 10-variant pool; mixed sizes do not.               |
