← Back to Tutorials
Advanced~15 min readUE 5.5 / 5.6

Cook & Packaging Performance

Cook time is iteration tax. Epic Games Japan reported a 14× speedup on iterative cooks (815s → 58s) using multi-process cook with UE 5.4. UE 5.5 added Zen Server as production-ready shared DDC, UE 5.6 added BC7-RDO encoding 25–30% faster, and UE 5.7 fixed ~99% of incremental-cook false-positive recooks. This tutorial covers the cook pipeline, DDC strategy, the multi-process / iterative / incremental cook ladder, IoStore vs pak vs Zen, and the regressions to gate in CI.

1

The cook pipeline at a glance

Editor → CookCommandlet → staging → pak / IoStore / Zen container. Time goes to:

  • Asset compile (textures, meshes, navigation).
  • Shader compile (largest line on most projects; can take hours).
  • Package serialize.
  • Container build (pak/IoStore/Zen).

Most cook-time wins come from (1) reducing the surface (skip editor-only content, deduplicate via Shader Permutation Reduction), (2) parallelizing (multi-process cook), and (3) caching aggressively (DDC + iterative/incremental).

2

DDC strategy — local, shared, Zen

Three layers of derived data cache:

  • Local DDC — per-engineer NVMe SSD. Default ~200–500 GB. Fast warm hits; cold miss falls through.
  • Shared DDC — UNC path (filesystem) or S3 bucket (cloud). Multi-TB. Team-wide cache; warm hits across machines.
  • Zen Server — UE 5.5+ default for new projects. Replaces filesystem shared DDC for production. Ships zen.exe, runs as a service, supports hot/cold tiering.

The senior pattern: UE-LocalDataCachePath + UE-SharedDataCachePath env vars override DefaultEngine.ini. Verify with DerivedDataCache.DumpUsage — reading INI alone doesn't tell you what's actually being used.

3

Zen Server deep dive

Zen does three things:

  1. Zen as DDC — replaces filesystem shared DDC. Better invalidation, hot/cold tiers.
  2. Zen as cooked output storebUseZenStore=true in DefaultGame.ini (or "Use ZenStore as cooking output" in Project Settings). Replaces pak as the storage backend for cooked content.
  3. Zen Loader — default-on in 5.5. Cuts runtime dependency-graph processing "from seconds down to milliseconds" by moving EDL prep offline (per Epic Zen Loader docs).

Configure auto-launch:

Engine.ini
[Zen]
AutoLaunch=true

Zen's local-project store lives under %LOCALAPPDATA%\UnrealEngine\Common\Zen\ by default; teams have hit C: drive exhaustion until they redirect.

4

IoStore vs pak vs Zen container

Three cooked output formats:

  • pak — UE4 legacy. Single .pak archive per chunk.
  • IoStore (.ucas/.utoc) — UE 5.0+. Optimized for SSD streaming. Default for shipped UE5 titles.
  • Zen container — 5.5+ next-gen. Runtime-streamable, supports IoStoreOnDemand for install-on-demand patterns.

Zen Server on PS5 streaming: ~1.8× faster app launch, ~3.1× faster map loads vs pak (per Unreal Fest 2024).

5

Multi-process cook

Multi-process cook (Director/Worker model) shipped in 5.3 stable. Configuration:

DefaultEditor.ini
[CookSettings]
CookProcessCount=8       ; Worker count; tune by RAM, not just cores

Or via UAT BuildCookRun: -AdditionalCookerOptions="-cookprocesscount=8".

Scaling: doubling cores does not double throughput — each worker needs its own RAM (~8–16 GB), shader compilation contention dominates above ~6 workers on most projects. Sweet spot is typically 4–6 workers on a 32 GB build farm machine.

Project path canonical-form gotcha -CookProcessCount=N workers crash if the .uproject isn't at the canonical UnrealEngine/<Project>/<Project>.uproject-style path. Persists in projects with relocated uprojects.
6

Iterative vs incremental cook

  • -iterate — reuses Saved/Cooked/ from prior cook. Fast for unchanged content. Epic UE 5.4 reported 815s → 58s (~14×).
  • -cookincremental — UE 5.5+; Zen-aware incremental cook. Reports Packages Cooked: N, Packages Iteratively Skipped: M.

UE 5.6 ships ~20% recook rate due to non-deterministic dependencies. UE 5.7 fixes ~99% of engine-type incremental dependency false positives. For project script types, opt in explicitly:

DefaultEditor.ini
[CookSettings]
+IncrementalClassScriptPackageAllowList=Allow,/Game

Validate with BuildGraph task IncrementalValidate -diffonly — detects false incremental skips.

7

Cooker memory tuning

BaseEditor.ini defaults
[CookSettings]
MemoryMaxUsedPhysical=16384    ; MiB cap on cooker
MemoryMaxUsedVirtual=0         ; 0 = unlimited
MemoryMinFreePhysical=1024     ; MiB headroom requirement

ShaderCompileWorkers can blow through 32 GB during cook; throttle with r.ShaderCompilingMaxMemoryPercentage. On 32 GB build farms with 6 multi-process workers + ShaderCompileWorker fan-out, OOM is the typical failure mode — cap memory aggressively.

8

Build farm cooks

The shipped pattern for shipping titles: Horde + Zen shared DDC + Zen cook snapshots + -buildmachine. The flags:

UAT BuildCookRun (build-farm)
RunUAT BuildCookRun -project=YourGame.uproject ^
    -platform=Linux+Win64 ^
    -cook -stage -archive ^
    -archivedirectory=Builds/ ^
    -unattended -buildmachine ^
    -compressed -pak -iostore

-buildmachine enables detailed cook timing CSV, error logging, no warning cap, no crash dialogs. -unattended suppresses modal dialogs (forgetting it = hung cook waiting on dialog).

Cook-time regression checklist

Run on every CI pull:

  1. Total cook wall time — alert if >X% above baseline.
  2. Incremental skip ratio — alert if it drops below project baseline (the canonical "non-deterministic dep crept in" signal).
  3. Per-class cook time deltas — texture, shader, world. Catches asset-class regressions.
  4. OOM tracking — ShaderCompileWorker memory peaks above headroom triggers alert.
  5. Final pak/IoStore/Zen size — alert on growth without corresponding feature flag.

PerfGuard can shell out to UnrealEditor-Cmd -run=cook -platform=... -unattended -trace=default -tracefile=<path> and parse the cooker summary line plus Unreal Cooking Insights trace. CI gate: alert when incremental skip ratio drops, when per-class cook time deltas exceed budget, when total wall time grows. Catches the silent regression Epic forums document — "code change quietly invalidates 20% more packages, adds 4–10 minutes per CI run."