Blog
October 7, 2026
Best Unreal Engine Version Control? Benchmarking Perforce P4, Lore, and More
Version Control,
Digital Creation & Collaboration
As part of my work, I regularly consult with teams comparing Unreal Engine version control performance and weighing whether Perforce P4 is the right fit for their projects. Based on these conversations, I decided to develop a repeatable framework that others can use to objectively benchmark P4 against other version control systems.
In this article, I explain why Unreal Engine version control performance should be tested against realistic project demands, outline the AWS environment and file dataset used to benchmark P4 and Lore, and share the commands and configuration details needed to reproduce the test. I also discuss what the results mean for teams choosing version control for Unreal Engine projects.
Key Takeaways from Benchmarking P4 vs. Lore
For the first comparison, I ran a test of P4 vs. Lore. If you’ve been keeping up with the space, you’ll know that Lore was recently announced by Epic Games (at Unreal Fest Chicago). I’ve been fielding a few questions on it, so I wanted to understand its performance with some actual numbers.
To evaluate how each system performs under realistic Unreal Engine workloads, I tested both platforms using a medium-scale UE dataset and measured common version control operations including add, submit, sync, and clone.
Key findings from the benchmark conclude:
- A P4 server configured through our Server Deployment Package (SDP) is 2.7x faster than Lore for submits of reasonable size.
For initial pulls (called 'syncs' in P4, or 'clones' in Lore), the speeds of P4 and Lore are similar, although Lore uses nearly 14x more memory.
The setup and P4 configurations that achieved this performance are shared below.
Back to topHow We Benchmarked Unreal Engine Version Control Performance
Unreal Engine has become a trusted game engine for creating immersive experiences and visualizations across industries. Unreal Engine projects introduce unique version control challenges, including time-intensive project setup, storage and transfer of large assets and binary files, and complex dependencies across teams and roles. Effective version control in Unreal is essential for protecting work, managing concurrent changes, and preventing collaboration bottlenecks as projects and teams scale.
The games development world ranges from small indie teams to AAA companies with many TB if not PB of data needing to be managed.
The UE example represents:
- Large numbers of text source files
- Many binary assets (.uasset/.umap), as well as graphics, video and audio – many of which compress fairly well
I chose to deploy P4 using our SDP or Server Deployment Package. The SDP is a set of scripts for Linux (or Windows) that not only help quickly and consistently install a P4 server with a good starting configuration and also includes scripts to make common operations easier (i.e., upgrading a server, setting up a replica server, creating a proxy server, etc.). My team continues to develop the SDP based on the needs of our customers, including major Enterprise deployments.
The actual server executable itself is exactly the same as a package install.
Test Environment
A lot of our customers use cloud infrastructure for flexibility and geo-distributed performance, so it makes sense to benchmark in the cloud, on an environment which can be easily reproduced.
For a medium-sized setup in AWS we use an EC2 instance m7a.2xlarge (8 CPUs, 32GB RAM) - which reflects common installations when working with Unreal Engine projects.
Software versions benchmarked were:
- Perforce 2026.1 (patch 2)
- Lore 0.8.5
AWS Server and Client Configuration
For ease of setup we deployed a server and a client machine. Since the client machine was very close to the server, the latency was minimal, which doesn’t really represent real-world situations where people often access the server from home or their office. To make it more realistic, we artificially introduced a 30ms latency on the client machine.
2 EC2 instances in AWS running Ubuntu 24.04:
- Benchserver: m7a.2xlarge with gp3 volumes (and listed IOPS/Throughput settings):
Git’s open-source nature makes it a versatile tool that can be freely used, adapted, and built upon, which is why it’s the basis for many popular platforms like GitHub, GitLab, and Bitbucket. These platforms extend Git's core functionality, offering collaboration features (pull requests, issue tracking), user-friendly interfaces (through tools like GitHub Desktop, GitKraken, Sourcetree), CI/CD pipeline integration, and code review workflows.
| Filesystem | Size | Mounted | IOPS | Throughput (MB/s) |
|---|---|---|---|---|
| /dev/nvme2n1p1 | 40G | /hxlogs | 10k | 500 |
| /dev/nvme3n1p1 | 50G | /hxmetadata | 10k | 500 |
| /dev/nvme1n1p1 | 750G | /hxdepots | 10k | 700 |
- This is a basic best practice installation using SDP (Server Deployment Package) with OS root volume and then 3 data volumes for journal/logs, database, and librarian or versioned files.
- The loreserver was deployed on /hxdepots (for all tests both servers were running, but only p4d or lore were active for any test)
- Benchclient: a slightly smaller c7a.xlarge with 200GB /data volume (10k IOPS, 500MB/s Throughput)
- Artificially increased latency between it and the benchserver to be 30ms using tc – (for details see testing with extra latency on Linux )
The Git Unreal Engine repo was downloaded (--depth 1) from Epic’s Gihub repo – so using this commit:
commit 71fe36aac5a8df5ccd66c763ffc902b29b6a9c43 (grafted, HEAD -> release, origin/release, origin/HEAD)
Author: UnrealBot <[email protected]>
Date: Tue Jul 28 12:02:51 2026 +0000
5.8.1 release I installed the package dependencies and ran Setup.sh to generate various intermediate files.
Building a Realistic Unreal Engine Test Dataset
The pure source files in the git repo do not represent a realistic Unreal Engine project since they consist of some 223k files but only 2.68GB of data.
A realistic project has a lot more data representing graphics, audio, video etc.
For this reason I chose to use the “Engine” directory and its contents, which after Setup.sh has been run represent a much more realistic 362k files with 91GB of data total.
This first command shows the source files from the git repo:
perforce@benchclient:/data/UnrealEngine$ git ls-files –cached –others –exclude-standard -z |
xargs -0 stat -c ‘%s’ |
awk ‘{s+=$1} END {
printf “Files: %d\nSize: %.2f GiB\n”, NR, s/1024/1024/1024
}’
Files: 223987
Size: 2.68 GiB So we use the Engine directory as a good approximation of a realistic data set:
perforce@benchclient:/data/UnrealEngine$ du -sh Engine/
91G Engine/
perforce@benchclient:/data/UnrealEngine$ find Engine/ -type f | grep -v .git | wc -l
362,028 Software Versions and Installation
Perforce p4d install per SDP Installation Instructions.
Lore install per Deploy a local Lore Server - Lore Developer Documentation
How Performance Was Measured
I also installed P4Prometheus, node_exporter and Grafana on both client and server machines with 15s scrape interval to be able to view graphs and record data for performance analysis.
Back to topBenchmark Results: P4 vs. Lore for Unreal Engine Projects
Adding and Submitting Unreal Engine Files
When adding new files, for P4 the commands used are: p4 add + p4 submit. For Lore it is stage + commit + push. I configured P4 to do the submit using parallel threads, to get a like-for-like comparison with Lore.
One thing to be aware of with P4 is the specification or detection of filetypes. By default, text files are stored as compressed (gzip’ed) files. Some binary files should not be compressed on the server (e.g. *.gz or some image formats). In most cases there are standard filetypes which are specified using the “p4 typemap” command.
If you don’t specify the filetype, then traditionally the P4 client would read a configurable amount of each file (default 64K bytes) to look for non-printable characters. For 362k files that is unnecessary overhead. P4 2026.1 avoids this overhead. If you are using earlier versions you may wish to use a typemap aware script, such as add_files_by_typemap.py.
Head-to-head totals (P4 = add + 10-thread submit; Lore = stage + commit + push):
| Metric | P4 total | Lore total | Who's better |
|---|---|---|---|
| Wall Clock (speed) | 5:15 | 14:30 | P4 faster - Lore takes 2.76x as long |
| Client User CPU (lower=better) | 178.16s | 1,278.59s | P4 lighter - Lore uses 7.18x more user CPU |
| Client Sys CPU (lower=better) | 81.42s | 152.85s | P4 lighter - Lore uses 1.88x more sys CPU |
| Client Max RSS / memory (lower=better) | 108 MB | 13,392 MB | P4 far leaner - Lore uses 124x more memory |
Some notes:
- Most server-side work for p4 happens in submit: CPU busy is 69.1%, with 32.51 GB disk writes.
- P4 submit scales well with parallelism
- lore stage is effectively all client-side, and is a bottleneck for lore
- lore commit concentrates server writes similarly to p4 submit: 35.43 GB disk writes at 18.6% disk busy, but with lower server CPU busy (13.8%).
- lore push remains metadata/light-I/O: negligible network and disk write volume.
📑 Additional Resource: Using Perforce as Source Control in UE [Epic Documentation]
Getting Files: P4 sync vs Lore Clone
| Metric | p4 sync (4 threads) | lore clone | Who's Better |
|---|---|---|---|
| Wall Clock (speed) | 3:10.09 | 3:22.12 | P4 faster - Lore takes 1.06x as long |
| User CPU (lower=better) | 278.47s | 211.10s | Lore lighter - uses 1.32x less user CPU |
| Sys CPU (lower=better) | 55.37s | 170.01s | P4 lighter - Lore uses 3.07x more sys CPU |
| CPU% | 175% | 188% | Roughly even |
| Max RSS / memory (lower=better) | 988 MB | 13,720 MB | P4 far leaner - Lore uses 13.9x more memory |
Notes:
- p4 sync was similar for 4 and 10 threads – clearly I/O limited
- Server-side, lore clone moved more network data: 51.95 GB TX vs 37.68 GB for p4 (~38% higher), while disk reads were similar (38.59 GB vs 37.15 GB).
- Server-side contention profile differs: lore clone shows higher iowait and busy (33.1% iowait, 40.4% busy) than p4 sync (14.9% iowait, 18.3% busy).
Reproducing the UE Version Control Benchmark
P4 Server Setup
In summary:
- Create an appropriate depot (e.g. UE5) on the server (use P4Admin, CLI shown below)
- Typically create an appropriate stream within that depot (use P4V), e.g. //UE5/main
- Create a list file containing all files to add
- Create a client workspace on the client machine specifying that stream
- Run the “p4 add” command
- Run the “p4 submit” command
📑 Additional Resource: Perforce P4 Beginner Guide Tutorials
Steps using CLI:
$ p4 --field Type=stream depot -o UE5 | p4 depot -i
$ p4 stream -t mainline -o //UE5/main | p4 stream -i
$ cd /data/UnrealEngine
$ find Engine/ -type f | grep -v .git > ../filelist.txt
$ p4 --field Stream=//UE5/main client -o Bench_ws | p4 client -i
$ nohup /usr/bin/time -v p4 -Ztrack -x ../filelist.txt add > ../add.out &
$ nohup /usr/bin/time -v p4 -Ztrack submit -d “New files” > ../submit.out & Note that using “/usr/bin/time” outputs detailed timing info. The “p4 -Ztrack” option will also output track info which helps to measure performance.
You can then review the data in the output files.
For syncing of files:
- Create a new client workspace on the client
- Run “p4 sync” command
Steps:
$ mkdir /data/ws2
$ cd /data/ws2
$ p4 --field Stream=//UE5/main client -o Bench_ws2 | p4 client -i
$ nohup /usr/bin/time -v p4 -Ztrack sync --parallel=threads=4 > ../sync.out & 📑 Additional Resource: Perforce P4 Admin Guide Tutorials
Lore Setup and Commands
$ lore repository create lore://benchserver:41337/UE5
$ cd /data/UnrealEngine
$ nohup /usr/bin/time -v lore stage --targets ../file_list.txt > ../stage.txt &
$ nohup /usr/bin/time -v lore commit “Test of UE5 Engine” > ../commit.txt &
$ nohup /usr/bin/time -v lore push > ../push.txt & Then to “sync”:
$ mkdir /data/lore_ws
$ cd /data/lore_ws
$ nohup /usr/bin/time -v lore clone lore://benchserver:41337/UE5 > ../clone.txt & P4 Server Configurables
These were standard for an SDP setup. Default parallel settings are typically 4 threads, but can be increased to 20 for specific commands. One addition was to set filesys.binaryscan=0 to avoid unnecessary file scans.
$ p4 configure show
P4ROOT=/p4/1/root (-r)
P4PORT=ssl:1666 (-p)
P4JOURNAL=/p4/1/logs/journal (-J)
P4NAME=master.1 (serverid)
P4LOG=/p4/1/logs/log (-L)
P4TICKETS=/p4/1/.p4tickets
P4TRUST=/p4/1/.p4trust
security=4 (configure)
monitor=2 (configure)
journalPrefix=/p4/1/checkpoints/p4_1 (configure)
filesys.P4ROOT.min=100M (configure)
filesys.P4JOURNAL.min=100M (configure)
filesys.P4LOG.min=100M (configure)
filesys.TEMP.min=100M (configure)
filesys.depot.min=100M (configure)
server.depot.root=/p4/1/depots (configure)
server.extensions.dir=/p4/1/logs/p4-extensions (configure)
serverlog.file.1=/p4/1/logs/auth.csv (configure)
serverlog.file.3=/p4/1/logs/errors.csv (configure)
serverlog.file.7=/p4/1/logs/events.csv (configure)
serverlog.file.8=/p4/1/logs/integrity.csv (configure)
serverlog.file.11=/p4/1/logs/triggers.csv (configure)
serverlog.retain.1=21 (configure)
serverlog.retain.3=21 (configure)
serverlog.retain.7=21 (configure)
serverlog.retain.8=21 (configure)
serverlog.retain.11=21 (configure)
server.rolechecks=1 (configure)
rejectList=P4EXP,version=2014.2 (configure)
monitor.lsof=sudo /usr/bin/lsof -F pln (configure)
auth.id=p4_1 (configure)
client.readonly.dir=client.readonly.dir (configure)
client.sendq.dir=client.readonly.dir (configure)
rt.monitorfile=monfile.mem (configure)
server: 4 (configure)
track: 1 (configure)
db.monitor.shared: 4096 (configure)
db.reorg.disable: 1 (configure)
dm.info.hide: 1 (configure)
dm.keys.hide: 2 (configure)
dm.protects.hide: 1 (configure)
dm.shelve.promote: 1 (configure)
dm.user.loginattempts: 7 (configure)
dm.user.noautocreate: 2 (configure)
dm.user.resetpassword: 1 (configure)
dm.user.setinitialpasswd: 0 (configure)
filesys.binaryscan: 0 (configure)
filesys.bufsize: 1048576 (configure)
lbr.autocompress: 1 (configure)
lbr.bufsize: 1048576 (configure)
lbr.unloaddepot.compress: 1 (configure)
net.keepalive.disable: 0 (configure)
net.keepalive.idle: 180 (configure)
net.keepalive.interval: 15 (configure)
net.keepalive.count: 9 (configure)
net.parallel.max: 20 (configure)
net.parallel.threads: 4 (configure)
net.parallel.submit.threads: 4 (configure)
net.parallel.sync.svrthreads: 150 (configure)
net.backlog: 2048 (configure)
proxy.monitor.level: 3 (configure)
rpl.checksum.auto: 1 (configure)
rpl.checksum.change: 2 (configure)
rpl.checksum.table: 1 (configure)
rpl.compress: 4 (configure)
run.users.authorize: 1 (configure)
server.commandlimits: 2 (configure)
server.locks.global: 1 (configure)
server.global.client.views: 1 (configure)
server.maxcommands: 2500 (configure)
server.start.unlicensed: 1 (configure)
filetype.bypasslock: 1 (configure)
submit.noretransfer: 1 (configure)
sys.pressure.mem.high: 0 (configure)
sys.pressure.mem.medium: 0 (configure)
rpl.forward.login: 1 (configure)
auth.sso.allow.passwd: 1 (configure)
auth.sso.nonldap: 1 (configure)
serverid=master.1 (serverid) Back to top
Choosing Between P4 and Lore for Unreal Engine
Both Lore and P4 perform well when suitably deployed. However, Lore defaults to lots of parallel processing and is pretty memory hungry by default.
For adding and submitting large Unreal Engine datasets, P4 was considerably faster than Lore.
P4 is both slightly faster for sync vs Lore clone and cheaper on egress (~38% less data transferred), while also keeping a much lower client RAM profile. Lore may still offset some costs through server-side deduplication for asset-heavy workloads, but that needs to be quantified against higher transfer volume and larger client instance sizing.
P4's lower egress and dramatically lower client memory footprint may give it a reasonable cost advantage at scale in cloud (allowing smaller/cheaper client instances to be deployed).
Why P4 Is the Best Version Control for Unreal Engine Teams
A version control repository is often an organisation’s crown jewel because it protects valuable intellectual property. In today’s fast-evolving game development environment, selecting a version control with strong performance and consistent support for globally distributed teams are vital.
There are good reasons why P4 has long been used for game development. It scales reliably across many terabytes of data, while features such as exclusive locking for binary and other unmergeable files support both developer and artist workflows. P4 also offers a broad ecosystem of support, integrations with Unreal Engine, and graphical tools, giving teams extensive industry knowledge and experience to build on. Backed by world-class support from Perforce, these capabilities have helped make P4 the industry-standard version control platform for Unreal Engine development.
Run the Benchmark for Unreal Engine Version Control
If you’d like to see how P4 stacks up to your current version control system, you can try P4 free for up to 5 users and 20 workspaces.