This object is in archive! 

Performance: Pre-calculate or cache MyDefinitionId.ToString results

Guest shared this bug 2 years ago
Solved

Game version: 1.200.032

Method: MyDefinitionId.ToString

This method is called frequently, it also allocates memory. There are only 1000-1500 distinct definition IDs to format (depending on mods), so these are cacheable without expiration.

Measured 1.9% CPU load just on this formatting method on a multiplayer server, which is too much for basically nothing.

Replies (5)

photo
1

Hello, Viktor!

Thank you for letting us know about this. I have reported this internally.

Kind Regards

Laura, QA Department

photo
1

Hello, Viktor!


I haven't found situation where it can drain 1.9% CPU. How do you measure?

If you use dot.Trace, could you please attach file?


Kind Regards

Gregory Smirnov

photo
1

That was measured of a local copy of a big server having hundreds of grids.

What I wrote in the description applies regardless. There is a good opportunity to cache the formatted definition IDs here, which will give some speedup in all cases.

Main reason for the speedup is that string formatting allocates memory, while retrieving the already formatted string from a dictionary does not allocate any memory. It removes some GC pressure, which always helps with performance regardless.

photo
1

Hello, Engineer,

I'm happy to announce that this issue is already fixed in the new version 202.

I will close this thread now as solved.

Kind Regards

Keen Software House: QA Department

photo
1

While the caching added in 1.202.066 works, it can also deadlock:

https://support.keenswh.com/spaceengineers/pc/topic/27997-servers-deadlocked-on-load


Lock contention will also lower the performance, so prefer solving it without locking instead.


What would work is adding a read-only dictionary to use directly (without locking) for lookups as a primary cache. If not found, then a secondary read-write cache is used with a regular mutex and newly formatted strings are cached there.


From time to time or if the number of items in the secondary cache exceeds a threshold the union of the primary and secondary caches are produced and the primary cache is replaced by just overwriting its reference (atomic operation). The old primary cache will be just garbage collected. Since basically no new strings are formatted after the game loads it will be very performant.


The above solution had been tested in the Performance Improvements 1.10.5 with game version 1.201.014 (previous release) for almost a year.


This was the implementation as a Harmony patch:

https://github.com/viktor-ferenczi/performance-improvements/blob/a952fb9b7166882bccbd3cb44fd683a64c1779a3/Shared/Patches/Memory/MyDefinitionIdToStringPatch.cs


The two-layer cache implementation:

https://github.com/viktor-ferenczi/performance-improvements/blob/a952fb9b7166882bccbd3cb44fd683a64c1779a3/Shared/Tools/CacheForever.cs

photo
1

Hello, Engineers!


We're happy to inform you that the upcoming "203" update contains a fix for the bug you have reported. Thank you for taking your time to inform us about this issue and making Space Engineers better.


If you are still experiencing the bug on the new version, please let us know by commenting here or opening a new thread.


We are closing this thread as "Solved".


Kind Regards,

Keen Software House: QA Department

Replies have been locked on this page!