This change includes timing updates as well as performance updates to reduce the number of garbage collections happening in the background.
Timing Updates
Completely reworked my timing system to be tick-based like the vanilla client.
Timestamp measurements:
Action
Original Client
EndlessClient
Walk
48
48
Attack
60
61
Approach:
Remove System.Diagnostics.Stopwatch and use monogame's frame update GameTime for all animation timing
On each Update() call, increment a global Tick
Store Tick value when an animation starts
Compare Tick difference when updating animation frames
Animation timing based on elapsed EO ticks rather than stopwatch millisecond differences
EO timestamp is now just the value of Tick since they're updated every 10ms
The end result is that there's a single place where animation timings are tracked. The behavior is now significantly more consistent and closer to vanilla.
Fixes #299
Memory usage updates
Updated PELoaderLib to use Span<T> and Memory<T> to load data, and removed ImageSharp as a dependency in the texture loading pipeline. This reduces the number of intermediate heap allocations and data copies when converting a texture from a PE resource to a Texture2D. This relies on some unsafe code and pointer arithmetic for high performance and reduced memory footprint
Additionally, found a couple memory hotspots where lots of allocations were happening:
A texture was being reloaded from disk in each Draw call in StatusBarLabel
NPCs on mouse over were calling GetData in each Update call
StatusBarLabel texture is now just loaded once, and NPCs now use an LRU caching mechanism to store the pixel data of the underlying textures. This has an increased memory footprint, but reduces the number of GetData calls needed, which reduces the number of heap allocations and eventual garbage collections.
This partially addresses #230 but more work still needs to be done
This change includes timing updates as well as performance updates to reduce the number of garbage collections happening in the background.
Timing Updates
Completely reworked my timing system to be tick-based like the vanilla client.
Timestamp measurements:
Approach:
System.Diagnostics.Stopwatch
and use monogame's frame updateGameTime
for all animation timingUpdate()
call, increment a globalTick
Tick
value when an animation startsTick
difference when updating animation framesTick
since they're updated every 10msThe end result is that there's a single place where animation timings are tracked. The behavior is now significantly more consistent and closer to vanilla.
Fixes #299
Memory usage updates
Updated PELoaderLib to use
Span<T>
andMemory<T>
to load data, and removedImageSharp
as a dependency in the texture loading pipeline. This reduces the number of intermediate heap allocations and data copies when converting a texture from a PE resource to aTexture2D
. This relies on some unsafe code and pointer arithmetic for high performance and reduced memory footprintAdditionally, found a couple memory hotspots where lots of allocations were happening:
Draw
call inStatusBarLabel
GetData
in eachUpdate
callStatusBarLabel
texture is now just loaded once, and NPCs now use an LRU caching mechanism to store the pixel data of the underlying textures. This has an increased memory footprint, but reduces the number ofGetData
calls needed, which reduces the number of heap allocations and eventual garbage collections.This partially addresses #230 but more work still needs to be done