Skip to content

Performance

Vitaly Murashov edited this page Oct 3, 2026 · 1 revision

Performance

All numbers below were measured on the same machine with a Release build (gcc -O3, Ninja, mingw-w64) and a real 196 700 record cache (D:\FS Cache\texturecache, ~7.3 GiB of .texture shards).

Item Value
CPU Intel Pentium Gold G5400 @ 3.70 GHz, 2 cores / 4 threads
Input first 120 decodable records (--limit 120), 83 of them truncated (69 %; cache wide 58 %)
Output 65.9 MB of PNG, i.e. ~0.55 MB per texture
Command SLTextureDecoderGUI.exe --batch --jobs N --cache-dir ... --out-dir <temp> --limit 120
Jobs Wall clock Per texture Throughput Speedup
1 49.3 s (first, cold OS cache) / 44.3 s (repeat, warm) 0.37 s 2.7 textures/s 1.0x
4 18.3 s (cold) / 17.5 s (warm) 0.15 s 6.8 textures/s 2.5 - 2.7x

Two runs, one with a cold OS file cache and one warm, are listed on purpose: the difference is ~10 %, so the gain is real parallelism rather than caching.

The output is deterministic

The PNG bytes do not depend on the number of worker threads or on the run order: aggregating a SHA-256 over all 120 output files gives the same value for --jobs 1 and --jobs 4, on the cold and on the warm run:

0CD4E06B4EE1DD1D046E5B277884E65F...   (120 files, jobs = 1 or 4)

That makes --jobs a pure performance knob: two people converting the same cache get byte-identical files, and a conversion can be resumed with a different thread count.

Memory

Measurement Value
Peak working set, --jobs 4, 120 records 76.2 MiB
Rough model per worker decoded component planes + the RGBA8 buffer, ~30 MiB for a 2048x2048 texture

One texture is alive per worker at a time. The budget therefore scales with jobs, not with the number of textures; a 4 GiB machine handles --jobs 4 even on a cache full of 2048x2048 textures. texture.entries (~5.5 MB) is held in memory, texture.cache and the body files are read by offset on demand.

The pool is capped at 32 workers on purpose.

Extrapolating to a whole cache

--jobs 1 --jobs 4
54 825 live records of the reference cache ~5 h 40 min ~2 h 15 min
Output at 0.55 MB per PNG (see the caveat below) ~30 GB ~30 GB

Treat these as order of magnitude: the 120 record sample is simply the first 120 records in cache index order (an arbitrary mix of sizes and completeness), PNG size depends on the content, and a bigger cache also benefits more from the OS file cache.

Where the time goes

  • OpenJPEG decode and PNG deflate are the CPU cost; both are per texture.
  • Reading the cache is cheap (600 bytes plus the body file per record), writing the PNGs is not - the sample wrote 65.9 MB of PNG for a much smaller amount of codestream input.
  • The viewer's codestreams are single tile, so one texture never uses more than one thread. --jobs parallelises between textures, which is why two physical cores cap the speedup at ~2.5x even with four threads available.
  • The input disk, the output disk and the CPU share the same bus on a small machine; putting the output on a second drive helps a little, a fast SSD helps more.

Tuning

Goal Setting
Fastest full run SLTextureDecoderGUI.exe --batch --jobs <logical CPUs> ... (the GUI default)
Keep the machine responsive --jobs 2
Repeat/resume a long run just run the same command again - existing PNGs are skipped
Halve the work --complete-only (writes only the records that are complete on disk, ~42 % of the cache)
Smallest output --complete-only plus a look at the result list sizes before you keep everything

The CLI binary is deliberately single threaded; use the GUI binary's --batch mode for anything long. To measure your own machine:

Measure-Command {
    .\build\bin\SLTextureDecoderGUI.exe --batch --jobs 4 --cache-dir "D:\FS Cache\texturecache" `
        --out-dir D:\textures --limit 200
}

Clone this wiki locally