---
id: uefn-performance-audit
title: UEFN island memory and performance audit
tags:
  - memory
  - performance
  - project-size
  - spatial-profiler
  - timing-insights
guide_slug: measuring-island-memory
when_to_use: Before measuring island memory, download size, or startup frames in UEFN. Call get_skill('uefn-performance-audit') first. Memory Calculation, Project Size, Memory Snapshot, Spatial Profiler, and Timing Insights are separate numbers. Does not audit material instruction count (that is get_skill('uefn-materials')), does not open the editor, and does not invent a download cap.
---

# UEFN island memory and performance audit

Call this skill **before** measuring island memory, download size, or
startup frames. This page is the hosted playbook. Do not invent a second
one.

It says which Epic panel to open, which number that panel actually
reports, and which workstation script collects the files. It does not
click the editor. Hosted MCP cannot launch a session.

LOOKUP ORDER:

1. `get_skill('uefn-performance-audit')` (this page).
2. On the editor machine, the uefn-mcp client scripts under
   `skills/uefn-performance-audit/scripts/`: `collect_evidence.py`,
   `export_timing_insights.py`, and `audit_capture_bundle.py`. If local
   `tools/list` has a tool that runs one of those scripts, call the
   tool. Do not write a second collector.
3. `search_verse_kb` `mode=docs` for the Epic page named in the section
   you are reading. `mode=howto` for the public guide
   `measuring-island-memory`.
4. Material instruction count, texture samples, and translucency stay on
   `get_skill('uefn-materials')`. Do not paste that checklist here.

## What this covers, and what it does not

Use it when you need an island-wide pass: the publish memory bar, cook
upload and download size, a play-session memory snapshot, a Spatial
Profiler heatmap, or a Timing Insights hitch / startup read.

Do not use it to author a master material, an instance tree, a
transparency trick, or a mobile sample-count audit. That budget is
`get_skill('uefn-materials')`: instruction count, texture samples, and
translucency. A material sample count is not the 100,000-unit bar.

Do not use it to open the editor, launch a session, or push changes.
Those clicks stay on the workstation. Do not use it to invent a numeric
upload cap, download cap, startup millisecond budget, or megabyte
stand-in for the publish bar. Current Epic pages do not publish those
numbers.

## Five measurements, never added together

Report each row on its own. Do not add them. Do not substitute one for
another.

| Measurement | Where | What the number is |
|-------------|--------|--------------------|
| Memory Calculation | Project, Launch Memory Calculation, then the in-client bar | Cook-time, edit-time units. Bar max is 100,000. Any area over 100,000 cannot publish. Not play-time. |
| Project Size | Project, Project Size, after a Launch Session cook | Cook size on disk. Upload Size and Download Size. Download Size is padded for consoles. Not the 100,000 bar. |
| Memory Snapshot | Spatial Profiler, Take Memory Snapshot, local PC client only | Play-session assets that are loaded now. Estimated Size is system RAM plus video, in Mb. |
| Spatial Profiler | Tools, Profile, Spatial Profiler, or the Game Performance button | Heatmap. Memory Usage is KB of the platform executable. Profile thresholds do not change the Memory Usage numbers on the Game Performance Monitor. |
| Timing Insights | Tools, Profile, Timing Insights, or Spatial Profiler Frame Time, Start Capture | One slow frame versus a cost that stays high. Inclusive time includes children. Exclusive time does not. |

Memory Test Results (Window, Message Log) is the top 100 contributors
to the **bar at the sampled location**. Columns: Resource, Type, number
of actor refs, number of package refs, Size. That Size is contribution
to the bar, not a play-time megabyte figure. A row typed Fortnite Asset
was not authored in the project and still counts.

## Editor pass (workstation)

Example project name: **MyProject**. Use the project that is open. Do
not invent a folder path.

1. Launch Session with **Monitor Performance** checked. Without that
   checkbox, Spatial Profiler and Memory Snapshot are not available.
   Live Edit and the Phone Tool do not refresh cooked data. Push Changes
   before you trust the bar, or the bar is stale.
2. Project, Launch Memory Calculation. Upload Private Version. Optional
   description. Read the result in the client, then Continue. With
   streaming on, fly: the bar is calculated from player position, and
   some assets stay loaded everywhere.
3. Window, Message Log, Memory Test Results. Record the top rows at
   that location.
4. After the cook from Launch Session: Project, Project Size (or the
   viewport widget). Stats: Last Uploaded, Upload Size, Download Size.
   Graph: By Type, By Package, Relative to Project Size, Relative to
   Largest Item, Show Dependencies. Refresh after Push Changes.
5. Spatial Profiler: launch a local play session and move the pawn.
   A warning icon plus Investigate means a metric crossed that
   profile's threshold. Profiles: Desktop, Console (Gen 8, Gen 9,
   Portable), Mobile, Default. Cell method default is Median. The
   Loading Range heatmap is not synced to World Settings; set it
   yourself. Double-click teleports the editor camera, and the pawn
   too when a session is running.
6. Memory Snapshot: under Memory, select the metric and Take Snapshot.
   Locally launched **PC** clients only. Not available for Mobile,
   Remote PC, or Console. Spatial Profiler metrics can still be
   collected from mobile; the snapshot cannot. Capture types: Detailed
   Insight (default; full resource size and references) and Quick
   Insight (skips recursive size; faster; less thorough). Snapshots
   are currently loaded assets only. Push Changes refreshes session
   data. Restart the session before another snapshot when you are
   testing Verse, devices, or gameplay, so unused objects clear.
   Filters default on: hide external, hide no referencing actors, hide
   no estimated memory. Optional: hide exclusive estimated memory below
   1 Mb; hide impact below 1%. Groups: Uncategorized, Texture, Static
   Mesh, Material Instance, Material Instance Dynamic, Material.
7. Timing Insights: Tools, Profile, Timing Insights, or Spatial
   Profiler, Frame Time, Start Capture (capture starts on its own).
   Closing the window stops capture. Hitch: zoom out, click the
   tallest bar, then the widest event, Enter to narrow, sort Timers
   by Incl. A big Incl and a small Excl means open Callees. The hot
   path follows the largest Incl. Epic's documented hitch example is
   GarbageCollection. Multi-frame: Timers Mode = Game Frame, drag the
   Time Ruler (it snaps to game frames). Documented columns include
   C.Avg (average instance count per game frame) and I.Avg (average
   inclusive time per game frame).
8. Primitive count is the Spatial Profiler metric **Primitive Count**.
   There is no Epic page titled Primitive Stats. In-game draw calls:
   Spatial Profiler Draw Call Count, or Settings, Game UI, (Creative)
   Runtime Performance Stats. Collect those in Play, not Edit. Nanite
   and non-Nanite counts differ.
9. Startup: Epic does not name a startup metric and does not publish a
   millisecond cap. Start the Timing Insights capture when the session
   becomes playable and read the first frames. Report that window.
   Do not invent a budget.

## Workstation scripts

The captures live on the editor machine. Run these from the uefn-mcp
client checkout (Python 3.10+, standard library). They work on files
only: they do not control the editor, upload, or delete content. Every
`--output` must be a new path; existing paths are refused.

```
D=skills/uefn-performance-audit
python $D/scripts/collect_evidence.py --config $D/templates/collection_config.template.json --output NEW_DIR
python $D/scripts/export_timing_insights.py TRACE.utrace --insights UNREAL_INSIGHTS_EXE --output NEW_DIR [--execute]
python $D/scripts/audit_capture_bundle.py init --output NEW_DIR
python $D/scripts/audit_capture_bundle.py review MANIFEST.json --output NEW_REPORT_DIR
```

- `collect_evidence.py` (`--config`, `--output`, both required) copies
  the Logs and exported files named in the config into a new bundle,
  with a hash receipt for every file. Export the panels in the editor
  first; the script does not read a live session. Collected files are
  unverified against a run unless the config pins exact source paths.
- `export_timing_insights.py` takes a completed `.utrace` and an
  explicit UnrealInsights executable (`--insights`, `--output`
  required). By default it only writes the plan, a response file, and
  a provenance manifest. `--execute` runs the export (threads, timers,
  events, statistics CSVs). Optional: `--timeout` (default 60 s),
  `--start-time` / `--end-time` in trace seconds and `--threads` /
  `--timers` filters, which narrow events only; statistics stay
  unfiltered. Use the start window for the startup read.
- `audit_capture_bundle.py init --output NEW_DIR` writes a starter
  manifest. `review MANIFEST.json --output NEW_REPORT_DIR` hashes the
  listed artifacts and writes `audit.json` and `report.html`. Exit
  codes: 0 PASS, 1 FAIL, 2 INCOMPLETE (or a malformed call). Readiness
  is a review of recorded evidence, not gameplay verification.
- `package_skill.py --output NEW.zip` zips the skill folder with a hash
  manifest. The zip must be new and outside the skill folder.

Each script also takes `--version`. Do not add switches the script
does not define. If `tools/list` already wraps a script, call that
tool. There is no hosted route for these scripts. Do not add one.

## Results contract

Fill every field. Write `not measured` plus the reason when a panel
could not run (mobile client has no Memory Snapshot; session launched
without Monitor Performance; and so on).

- `project` — open project. Examples use MyProject only.
- `fortnite_build` — the build label the editor shows, when the capture
  includes it.
- `memory_calculation` — sampled location, bar units, whether any area
  is over 100,000, and Memory Test Results rows (resource, type, actor
  refs, package refs, size contribution to the bar).
- `project_size` — Last Uploaded, Upload Size, Download Size. Do not
  convert these into bar units.
- `memory_snapshot` — client name, timestamp, Detailed Insight or Quick
  Insight, top rows (group, estimated size Mb, impact percent,
  references). If the client is not a local PC client, `not measured`.
- `spatial_profiler` — profile, metric, cell method, min / max / median,
  and whether a warning icon fired. Memory Usage stays in KB.
- `timing_insights` — capture window, tallest frame, widest event, Incl
  versus Excl, and whether the hot path is a callee. Startup is the
  first frames after the session is playable, with no millisecond cap.
- `reductions` — the next Epic step below, and which of the five
  numbers you will re-read after Push Changes.
- `not_measured` — the gaps you hit, in the words of the section
  "Where Epic is silent".

## Reductions Epic documents

Memory Calculation (cook / edit time):

- Stream textures. Power-of-two dimensions and mipmaps. MipGenSettings
  NoMipmaps fails publish validation.
- World Partition streaming on. Is Spatially Loaded, especially on
  Landscape streaming proxies.
- Spread density. Fewer unique devices; instances are cheaper than
  unique devices.
- Reuse assets. Lower distant LOD quality. HLODs only for objects that
  stay far. Data Layers for content that is not always needed.
- Nanite Keep Triangle Percent when a mesh is Nanite.
- Check Project Size after the memory pass. They answer different
  questions.

Draw calls (Play mode):

- Fewer material slots. Merge meshes. Instanced static meshes.
  LODs and HLODs.
- On platforms that run Nanite, Nanite meshes are one draw call per
  material.
- UEFN auto-instancing already merges an identical mesh plus material.
  Do not add a second instancing pass for that case.

Material instruction count, samples, and translucency are still
`get_skill('uefn-materials')`. Cutting a translucent blend can lower
frame time; it does not replace the 100,000-unit bar.

## Where Epic is silent

- The public Memory Management page makes the 100,000-unit bar the
  publish gate. It does not publish a separate megabyte threshold for
  Memory Test Results. Do not stamp a megabyte cap. Do not substitute
  Memory Snapshot Mb or Spatial Profiler Memory Usage KB for the bar.
- The Project Size page does not state a numeric upload cap or download
  cap. Report the sizes you measured. Do not invent a limit.
- Timing Insights does not publish green or red millisecond marks and
  does not define a startup budget.
- There is no page titled Primitive Stats. Use Primitive Count.
- Epic does not document a side effect from toggling Spatial Profiler
  metric checkboxes in the middle of a session. Set the metrics before
  you launch, and do not compare two captures whose checkbox history
  differs. A local observation that Memory Usage stepped up and stayed
  up after a mid-session toggle is a **hypothesis**, not a published
  limit. Re-check on the current build. Do not quote a megabyte figure
  for it.
- Console collaborators can hit a hardware limit even when you are not
  publishing. That is a device limit, not a second publish bar.

## EXAMPLE

MyProject, one pass, five numbers:

1. Launch Session, Monitor Performance on. Memory Calculation at the
   spawn: bar under 100,000. Memory Test Results names the textures
   that dominate that cell.
2. Project Size: record Upload Size and Download Size. Do not add them
   to the bar.
3. Local PC client, Detailed Insight snapshot at the same cell. Top
   group is Texture. A mobile client on the same pass is
   `not measured` for the snapshot; the heatmap can still be collected.
4. Spatial Profiler, Desktop profile, Memory Usage in KB, Primitive
   Count, Draw Call Count. Warning icon recorded or absent.
5. Timing Insights from the moment the session is playable. First
   frames are the startup read. Tallest later bar, if any, is the hitch
   (Incl, then Callees).
6. Workstation: `collect_evidence.py`, then
   `export_timing_insights.py`, then `audit_capture_bundle.py`.
7. One reduction (stream the oversized textures, or turn streaming on
   for the landscape proxies). Push Changes. Re-read only the rows that
   reduction can move.

## Siblings

- Material instruction count / samples / translucency →
  `get_skill('uefn-materials')`
- Build grid, piece sizes, LOD placement, galleries →
  `get_skill('uefn-building')`
- Prefabs and scene events → `get_skill('uefn-scene-building')`
- Live editor bind / inspect → `get_skill('epic-valkyrie-mcp')`
- Public walkthrough → guide `measuring-island-memory`

## Sources

Checked against the current Epic pages. If a page and this skill
disagree, the page wins; drop the sentence that conflicts.

- Memory and optimization hub: https://dev.epicgames.com/documentation/fortnite/memory-and-optimization-in-unreal-editor-for-fortnite
- Memory management and Memory Calculation: https://dev.epicgames.com/documentation/fortnite/memory-management-in-unreal-editor-for-fortnite
- Project Size: https://dev.epicgames.com/documentation/fortnite/project-size-tool-in-unreal-editor-for-fortnite
- Memory Snapshot: https://dev.epicgames.com/documentation/fortnite/memory-snapshot-in-unreal-editor-for-fortnite
- Spatial Profiler: https://dev.epicgames.com/documentation/fortnite/spatial-profiler-in-unreal-editor-for-fortnite
- Timing Insights in UEFN: https://dev.epicgames.com/documentation/fortnite/timing-insights-in-fortnite
- Reducing draw calls: https://dev.epicgames.com/documentation/fortnite/reducing-draw-calls-in-fortnite
