Skip to content

Performance Characteristics

The numbers here are expected worst-case numbers.

These were gathered from the original heavily optimized C# implementation of the VFS.

Some of these may improve a bit, others, not so much.

All numbers were obtained on a stock clock AMD Ryzen 5900X and 3000MHz CL16 RAM.

File Mapping Performance & Memory Usage

These are numbers from the original C# version.

We can save some additional memory in Rust with clever use of custom string pooling.
AHash is also a better hash algorithm. Expect both memory and speed numbers to improve a tiny bit.

This section describes how long it takes to create a file map.

A file map is used to redirect original files to their new versions found in mod folders.
Whenever changes are made to mod folders, a 'rebuild' of the map is done.

Two types of maps exist, RedirectionTree and LookupTree. The latter, LookupTree is optimized for performance, but takes roughly twice as long to build as it is built from the former RedirectionTree.

Folder Type Directories Total Items RedirectionTree (Time) RedirectionTree (Memory) LookupTree (Time) LookupTree (Memory)
Windows Folder 40,796 170,438 43ms 27MB 32ms 25MB
Steam Folder
(65 games)
9,318 172,896 18ms 12MB 20ms 11MB

The performance of mapping operations mainly depends on the directory count. The table above shows the time and memory usage for building the RedirectionTree and LookupTree for both Windows and Steam folders. The LookupTree memory usage should be approximately equal to the total runtime memory usage.

For a typical game (based on the median of a Steam library), building the RedirectionTree should take around 0.017ms and allocate 48KB. Creating the optimized LookupTree takes about 0.012ms (+ time taken for RedirectionTree) and allocates 47KB.

In other words, you can assume remapping files is basically real-time.

Fast Append

It's possible to skip a 'rebuild' in some situations.

Both LookupTree and RedirectionTree can have 'fast append' operations. (Just like in the original C# implementation)

If a file is added to the mod folder while the game is running and isn't previously mapped, it can be added to the tree directly without a full rebuild.

However, if the currently mapped file's source mod cannot be determined, the entire tree must be rebuilt.

This process doesn't require scanning mod folders again for files when not necessary. Each folder mapping can have a cache of subdirectories and files, and the same string instances can be reused between the trees and cache to save memory.

File Open Overhead

These are numbers for original C# implementation

File open has negligible performance difference compared to not using VFS. In a test with opening+closing 21,000 files (+70,000 virtualized), the difference was only ~41ms (~3%) or less than 2 microseconds per file.

// All tests done in separate processes for accuracy.
| Method                           |    Mean |    Error |   StdDev | Ratio |
| -------------------------------- | ------: | -------: | -------: | ----: |
| OpenAllHandles_WithVfs           | 1.650 s | 0.0102 s | 0.0095 s |  1.03 |
| OpenAllHandles_WithVfs_Optimized | 1.643 s | 0.0145 s | 0.0135 s |  1.03 |
| OpenAllHandles_WithoutVfs        | 1.602 s | 0.0128 s | 0.0120 s |  1.00 |

In real-world "cold-start" scenarios (e.g. after a machine reboot), opening these many files would take around 80 seconds, making this difference effectively margin of error (~0%).

Existing Benchmarks

A lot of microbenchmarks are available in the original C# project under the Reloaded.Universal.Redirector.Benchmarks project; have a look!