VaM LeanCore 0.8.0-RC1 - What Changed Since 0.7.0
Version 0.7.0 concentrated on large-library startup and morph demand loading. Version 0.8.0 extends LeanCore into runtime skinning and scene construction, with particular attention paid to repeated work inside plugin-heavy scenes.
The main additions are:
- Native x64 acceleration for VaM's hottest Person skinning loop.
- A persistent binary morph-descriptor index that reduces repeated package-morph import work while building Persons.
- A small validated cache for repeated clothing/hair catalog file discovery.
- Exact-input C# plugin compilation reuse within a scene and across VaM restarts.
- Per-instance assembly identity isolation and automatic persistent-cache invalidation/recovery.
- A generic demand-activation bridge for plugins that request geometry/morph: parameters directly.
Improvement matrix
Disclaimer
@Shadow Venom's
VaM Produce 69 was used as a stress-test workload because of its exceptionally demanding scene-loading and plugin-initialization requirements.
| Area | Original / 0.7 path | LeanCore 0.8.0 | Measured result |
|---|
| DAZSkinV2.SkinMeshPart hot loop | 24.31 aggregate worker-ms/frame | 4.95 worker-ms/frame | 79.6% lower; 4.91x faster |
| Official Benchmark Baseline 3 | 123.88 FPS | 139.38 FPS | 12.51% faster |
| Official Benchmark Simpler Physics | 156.41 FPS | 168.47 FPS | 7.71% faster |
| Three-Person structural scene load | 35-36 seconds | Approximately 28 seconds | 6.5-7.5 seconds saved; 18-21% lower |
| Three-Person package JSON demand parsing | 2,889 packages / 3.31 seconds | 2,043 packages / 1.09 seconds | 846 fewer parses; 2.22 seconds saved |
| Repeated clothing/hair file discovery | Twelve searches / 1.34 seconds | Four retained searches | Approximately 0.90 seconds of repeated work removed |
| VaM Produce 69 structural load | 174 seconds | 60-98 seconds observed | 76-114 seconds saved; 43.7-65.5% lower; 1.78-2.90x faster |
| VaM Produce 69 plugin synchronization | 134.98 seconds | 26.60 seconds in the fastest accepted memory-cache run | 108.39 seconds saved; 80.3% lower; 5.08x faster |
| VaM Produce 69 warm asset tail | Approximately 12-14 seconds | Approximately 11-14 seconds | No material change |
| VaM Produce 69 custom initialization | Approximately 70 seconds | Approximately 68-73 seconds | No material change |
The ranges above are intentional. I am reporting the repeatable observed range instead of publishing only the fastest stopwatch result.
1. Native Person skinning acceleration
VaM's DAZSkinV2.SkinMeshPart() is one of its hottest recurring CPU loops. LeanCore 0.8.0 moves that calculation into an independently implemented Windows x64 native module while retaining VaM's existing worker scheduling.
The implementation covers all six rotation orders, ordinary and general weights, bulges, fully weighted vertices, selective vertex/bone paths, early context preparation, reference-counted context ownership, and clean retirement after VaM's workers stop.
| Official Benchmark V5 metric | Original VaM | LeanCore 0.8.0 | Change |
|---|
| Overall average | 221.13 FPS | 228.07 FPS | +3.14% |
| Overall 1% low | 78.37 FPS | 76.92 FPS | -1.85% |
| Baseline 3 | 123.88 FPS | 139.38 FPS | +12.51% |
| Simpler Physics | 156.41 FPS | 168.47 FPS | +7.71% |
| Baseline 3 CPU time | 6.74 ms | 5.96 ms | -11.57% |
| Simpler Physics CPU time | 4.71 ms | 3.95 ms | -16.14% |
Direct profiling reduced SkinMeshPart itself from 24.31 to 4.95 aggregate worker-ms per frame. Numerical validation compared 64 independent work partitions across eight skin contexts with zero failures. The worst positional difference was 0.0000007153 against a 0.00002 acceptance threshold.
This does not guarantee higher FPS in GPU-bound scenes. The tested three-Person scene remained near 92 FPS because the RTX 4080 was already at 100% GPU usage, although LeanCore still reduced skinning work and freed CPU time.
If the native module is missing, incompatible, or rejected, LeanCore leaves VaM's original managed skinning path active.
2. Faster Person construction through persistent morph descriptors
Profiling showed that three Person atoms spent approximately 7-9 seconds repeatedly importing package morph metadata. The largest cost was not final lookup rebuilding; it was package JSON access, metadata parsing, morph construction, and sub-bank insertion.
LeanCore now maintains a validated binary descriptor index at:
Code:
BepInEx/cache/VaMLeanCore/morph-descriptors-v1.bin
The index represents immutable package morph metadata. Each Person still receives independent DAZMorph and formula instances. Demand activation, favorites, UID/name lookup, package identity, refresh invalidation, and original fallbacks remain intact.
- The tested library produced 17,115 indexed morph descriptors.
- Three People used 51,261 fast imports with zero fallbacks in approximately 1.26 seconds.
- Structural loading fell from 35-36 seconds to approximately 28 seconds.
- Package JSON demand parsing fell from 2,889 packages / 3.31 seconds to 2,043 packages / 1.09 seconds.
- The index validates in approximately 0.3-0.5 seconds on later runs.
- When PackageJSON is rebuilt, descriptor capture reuses the JSON nodes already parsed by the parallel cache builder instead of parsing everything twice.
- When PackageJSON is warm but the descriptor index is missing, LeanCore builds it in the background without blocking normal startup.
Changed, added, removed, missing, malformed, or stale packages invalidate or bypass the fast path safely. Corrupt-index, single-package rebuild, package timestamp change, package removal, and package restoration were all tested.
3. Clothing and hair catalog discovery
VaM repeated twelve clothing/hair FindAllFiles() searches while building three People. Those searches consumed 1.34 seconds; sorting was only about 4.6 ms.
LeanCore caches only the four relevant *.vam file lists and invalidates them before FileManager.Refresh. This eliminated eight repeated searches and removed approximately 0.90 seconds of work. It is a narrow optimization rather than a broad filesystem cache.
4. Why VaM Produce 69 was used
VaM Produce 69 was chosen as a stress workload because it is far heavier than an ordinary scene. It contains many atoms, lights, assets, triggers, embedded clothing plugins, and hundreds of plugin instances. That makes serial engine bottlenecks large enough to measure reliably.
The scene is only a test case. LeanCore contains no scene names, atom IDs, plugin identities, or content-specific allowlists. The optimization targets VaM's generic DynamicCSharp.Compiler.ScriptCompiler pipeline and therefore applies to any scene containing repeated identical C# plugin inputs.
Profiling found:
- 399 serial Atom.LateRestore calls consumed 135.39 seconds.
- 398 MVRPluginManager.LateRestoreFromJSON calls consumed 135.24 seconds.
- 289 SyncPluginUrlInternal calls consumed 134.98 seconds.
- The scene saved 301 plugin references but used only 67 unique plugin URLs.
- 234 references, or 77.7%, repeated scripts that original VaM compiled independently.
5. Exact-input plugin compilation reuse
LeanCore caches only successful symbol-free compile requests with exact matching inputs. Failed compilations and unsupported/debug-symbol paths retain VaM's original behavior.
Every reuse still receives a unique generated assembly name, module name, and MVID. VaM then performs its normal assembly security checks, load, controller creation, Awake, Init, InitUI, and restore work. LeanCore does not merge plugin instances or skip custom plugin initialization.
The result on VaM Produce 69:
| Metric | Original VaM | LeanCore 0.8.0 |
|---|
| Structural scene load | 174 seconds | 60-98 seconds observed |
| Plugin synchronization | 134.98 seconds | 26.60 seconds in the fastest accepted memory-cache run |
| Repeated compile hits | 0 | 239 |
| Unique compile inputs | Repeated per instance | 67 |
The remaining plugin path includes controller/UI construction and custom plugin code. In the focused profile, plugin Init consumed 10.94 seconds and InitUI consumed 5.35 seconds. Those are plugin-authored operations and remain outside LeanCore's optimization scope.
6. Persistent plugin compilation cache
Successful unique compilations are persisted under:
Code:
BepInEx/cache/VaMLeanCore/plugin-compilation-v1
Keys include the exact source content or source-file identity, ordered references and signatures, generated assembly prefix, runtime identity, managed/BepInEx inventory, and the actual SHA-256 of Assembly-CSharp.dll.
- VaM Produce 69 stored 67 unique entries totaling approximately 3.55 MiB.
- Writing all 67 entries took 54.1 ms.
- A later restart read all 67 entries in 29.1 ms.
- The persistent path saved approximately 3-18 seconds of measured compile/rewrite work after restart, depending on run variance.
- The cache uses atomic writes and SHA-256 payload verification.
- It is limited to 4,096 entries or 256 MiB and prunes older entries by timestamp.
- VaM's Clear Cache button does not delete this BepInEx-derived cache.
A deliberate corruption test rejected only the damaged entry, compiled it normally in 174.4 ms, repaired it, and returned to 67/67 persistent hits on the following restart.
7. Direct morph-parameter compatibility bridge
Some animation/control plugins request a Person's geometry/morph: float parameter directly instead of first calling VaM's morph-bank lookup. With package morph preloading disabled, that parameter may not yet be registered.
LeanCore now recognizes a failed geometry/morph: or geometry/morphOtherGender: lookup, calls VaM's own GetMorphByDisplayName demand-activation path, and registers only the requested morph. The implementation contains no Timeline- or package-specific code.
This was validated against a real Timeline scene that previously dropped two existing AshAuryn morph tracks. After the bridge, the warnings disappeared, telemetry recorded the expected direct activations, and the scene remained functional.
8. Texture loading experiment - measured, rejected, and not shipped
Texture loading was investigated in depth during 0.8 development.
On the three-Person test scene, 43 uncached source textures expanded to 6,097.1 MiB. Original VaM spent about 31.02 seconds preprocessing them and 17.98 seconds on ordered main-thread finalization/compression/cache output. A bounded four-worker prototype reduced the cold asset tail from 52 to 30 seconds:
| Three-Person cold texture test | Original VaM | Prototype | Change |
|---|
| Asset tail | 52 seconds | 30 seconds | 22 seconds saved; 42.3% lower; 1.73x faster |
| Full structure + asset completion | 87 seconds | 66 seconds | 21 seconds saved; 24.1% lower |
| Peak working set | Approximately 13.3 GiB | 20.67 GiB | Approximately 7.4 GiB higher |
That looked promising, but VaM Produce 69 exposed a serious scaling failure. Its 141 uncached sources interacted badly with whole-batch barriers, ordered finalization, memory retention, and storage queueing:
| VaM Produce 69 cold texture test | Original VaM | Four-worker prototype | Result |
|---|
| Asset tail | 55 seconds | 120 seconds | 65 seconds slower; 118.2% regression |
| Full scene completion | Approximately 257 seconds | Approximately 310 seconds | 53 seconds slower; 20.6% regression |
| Peak disk queue | Approximately 0.97 | 4.11 | Storage contention increased sharply |
Because an optimization that helps a moderate scene but badly regresses a large one is not release-safe, the parallel texture implementation and its configuration setting were removed from the final DLL. LeanCore 0.8.0 uses VaM's original texture path.
This remains a future research area. A safe redesign would require a memory-budgeted sliding prefetch window that waits only for the current queue head and counts completed-but-not-finalized decoded data against a conservative 32 GB system budget.
Test and compatibility summary
- Final populated library: 3,778 physical VAR archives / 236.20 GiB; 3,657 packages accepted by VaM.
- Official benchmark tests: 3,655 accepted packages at 1920x1080, 144 Hz, and 8x MSAA.
- Final RC passed ordinary desktop scenes and VaM Produce 69.
- Final RC was extracted directly over 0.7.0 in a fresh installation and loaded the plugin-heavy scene without LeanCore errors.
- Morphs, favorite morphs, direct morph animation parameters, hair, clothing, controls, triggers, audio, lights, and plugin-heavy behavior were exercised.
- An earlier 0.8 native-runtime build passed Virtual Desktop VR; the exact final RC VR smoke was not repeated.
Upgrading from 0.7.0
Close VaM and extract VaMLeanCore-0.8.0.zip directly into the folder containing VaM.exe. Allow the old LeanCore files to be overwritten.
Version 0.8.0 adds the required native companion:
Code:
BepInEx/plugins/VaMLeanCore/VaMLeanCore.Native.dll
The existing 0.7.0 configuration remains compatible. No new public runtime setting is required.
Download integrity
Code:
VaMLeanCore.dll SHA-256:
242F2C5D0D134561429A99F1DFD995A2F033249453AA2E161F798A02FB8FD736
VaMLeanCore.Native.dll SHA-256:
5AABD16288C15805A748952A256C1019E4D9FC8956029589474F00EB9A62F19B
VaMLeanCore-0.8.0.zip SHA-256:
FBCD7A239418763516E7B2FD5D561728817B365B779C72752E062E98E23A7C0A
Call For Testing
I found issues with timeline plugin that i have remediated. I am only human and can test so much. Please test and if you have any issues then reach out with error message and a link to the scene var so i can reproduce the error and remediate it.
Thanks and as always ENJOY!!!