Scroll down for:
- List of features
- Technical details
- Keen bug reports to vote on
For support please join the SE Mods Discord.
Please consider supporting my work on Patreon or one time via PayPal.
Thank you and enjoy!
- SE Mods Discord FAQ, Troubleshooting, Support, Bug Reports, Discussion
- Plugin Loader Discord Everything about plugins
- Install Plugin Loader into Space Engineers (add launch option)
- Enable the Performance Improvements plugin from the Plugins dialog
- Apply, restart the game
Select the Performance Improvements plugin from the plugin list inside the Torch GUI.
Please note, that the plugin is using Harmony to patch the game code. Once Keen fixes the issues these patches are expected to be removed anyway, so I did not bother using Torch's patching mechanism.
- Download the latest ZIP from Releases.
- Open the
Bin64
folder of your Dedicated Server installation. - Create a
Plugins
folder if it does not exists. - Extract the ZIP file into the
Bin64/Plugins
folder. - Right click on all the DLLs extracted and select Unblock from the file's Properties dialog.
- Start the Dedicated Server.
- Add the
PerformanceImprovements.dll
from theBin64/Plugins
folder to the Plugins list.
In alphabetical order
- BetaMark
- Bishbash777
- Casinost
- Dorimanx
- wafoxxx
- DontFollowOrders
- Gabor
- Lazul
- Lotan
- mkaito
- ransomthetoaster
- Raidfire
- Avaness: client side Plugin Loader
- Bishbash77: testing and keeping Torch alive
- mkaito: testing and design discussions
- zznty: contributed patches
- CaveBadgerMan: SG Dimensions, Torch servers
- Dorimanx: contributed patches
- mkaito: testing with his heavy offline world
- Robot10: client side
- Multiple server admins for testing and feedback
- zznty
Disables the MyConveyorLine.UpdateIsWorking
method while any grid merging operation is in
progress. It considerably reduces the merge time of grids with long conveyor systems. At the
end of MyCubeGrid.MergeGridInternal
it calls GridSystems.ConveyorSystem.FlagForRecomputation()
on the grid to force recalculating all IsWorking
values to fix any side-effects of the
optimization.
Disables updates while pasting grids by setting MySession.Static.m_updateAllowed
to
false
while MyCubeGrid.PasteBlocksServer
is running. It eliminates a lot of
unnecessary computations until the paste is done.
This one and the previous fix combined make grid merge and paste operations ~60-70% faster in my test world, at least for grids with lots of blocks and conveyor ports. It adds up on multiplayer servers, especially if NPC are pasted automatically.
Please vote on the support ticket
Eliminates 98% of the ~50% constant CPU core load imposed by the
VRage.EOS.MyP2PQoSAdapter.UpdateStats
method, even during offline games.
It is done by replacing 49 out of 50 calls with a Thread.Sleep(1)
.
It limits the outer loop's frequency to less than 1000/s and spends
less CPU power on gathering statistics.
It makes the game faster only if you have 4 or less CPU cores, since this method is called repeatedly in a loop on its own thread. It still helps to reduce CPU power consumption and cache misses if you have more than 4 cores.
Whether it affects the stability of multiplayer networking or any other EOS related functionality is yet to be seen.
Please vote on the support ticket
Contributed by: zznty
The game makes explicit calls to GC.Collect
, which may cause long pauses
while starting or stopping large worlds. It mostly affects large multiplayer
servers where worlds are big, but it can shave off a few hundred milliseconds
of world load (and close) time in case of loading offline games as well.
There are also calls elsewhere, for example in MyPlanetTextureMapProvider
and
MySimpleProfiler.LogPerformanceTestResults
, which may be invoked during gameplay.
The patched calls are now logged at the DEBUG log level, so we can see them and
measure how much we save by eliminating them.
Parallel GC should happen later and free up memory anyway. No explicit garbage collection calls should be needed anymore.
Consider disabling this setting if your PC or server does not have at least 8GB RAM.
TODO: Add a Keen support ticket after gathering profiling data.
Contributed by: zznty
It may be a performance hog if many mods are used. This fix disables the
VRage.Scripting.Rewriters.PerfCountingRewriter.Rewrite
method, so the
API calls are not rewritten, removing the overhead.
I hope it will not be a problem for Keen, as long as only a small minority of players are using plugins. It is not a bug, it is a feature. Therefore no support ticket is needed.
Measured 10% lower simulation CPU load in a heavily modded test world after loading it with this fix enabled.
There is some serious lag on connector lock/unlock and rotor head attach/detach due to grid group changes causing massive main thread workload, which could easily be deferred to worker threads with minimal consequences.
This fix disables resource updates while grids are being moved between groups and marks those resources for updating by a worker thread later.
Please vote on the support ticket
Compiling all mods and PB scripts on world load is very time consuming and CPU intensive. It takes a lot of time to load a world which uses many mods and/or in-game scripts. It mainly affects large multiplayer servers, but I have also seen advanced single player worlds affected by slow world loading.
Please vote on the support ticket
MySafeZone.IsSafe
is called very frequently for entities inside safe zones.
This is quite a bit of overhead in multiplayer worlds with many small grids and
safe zones in it, like the Alehouse Rover PvP one.
Workaround is to cache the result of MySafeZone.IsSafe for up to 128 simulation ticks (~2 seconds). Side effect of the fix is that grid ownership changes are reflected in safe zone behavior only up to 2 seconds later (1 second on average).
Please vote on the support ticket
1.203.022: While Keen reduced the GC pressure (memory allocations) by using a
ReuseCollection
, it is not enough. The main issue is repeating this
expensive check frequently without caching it. Therefore the caching
implemented by this plugin is still required.
MySafeZone.IsOutside()
is implemented in a convoluted way. Replaced it with
an optimized implementation which does not instantiate any new bounding boxes.
Replaced only the MySafeZone.IsOutside(BoundingBoxD aabb)
override, because
it caused issues with many grids around safe zones. The time spent in the
other two overrides were not significant, either they are used less or they
could be fully optimized by the JIT compiler eliminating the bounding box
objects.
Due to the high call counts of busy servers this method benefits from caching. The results is cached for 2 seconds, therefore the effect of changes in Safe Zone configuration or grid safe-zone containment is delayed by up to 2 seconds, which is acceptable considering the overall performance benefits.
Game update 1.202.066 (Automaton) attempted to fix the slowness, but introduced a deadlock as a result.
So the fix to MyDefinitionId.ToString
has been put back into this plugin.
There are large memory allocations in some frequently called routines, causing quite a bit of GC pressure:
MyLargeTurretTargetingSystem.SortTargetRoots
MyLargeTurretTargetingSystem.UpdateVisibilityCacheCounters
(this fix was disabled since 1.10.4 due to reported crashes)
Please vote on the support ticket
Since the result of MyWindTurbine.IsInAtmosphere
does not change often,
it can safely be cached for a few seconds.
Please vote on the support ticket
Suppresses frequent calls to MyPlayerCollection.SendDirtyBlockLimits.
Please vote on the support ticket
Caches the result of MySafeZone.IsActionAllowed and MySessionComponentSafeZones.IsActionAllowedForSafezone for 2 seconds.
Please vote on the support ticket
Suppresses frequent calls to MyGridTerminalSystem.UpdateGridBlocksOwnership updating IsAccessibleForProgrammableBlock unnecessarily often.
Please vote on the support ticket
NOTE: This fix has been disabled in 1.10.1 due to a bug, which has been fixed since. It may be re-enabled once tested carefully.
Caches the result of MyCubeBlock.GetUserRelationToOwner and MyTerminalBlock.HasPlayerAccessReason.
Keen introduced MyVRage.Platform.System.OptimalHavokThreadCount
, but it is set to null
.
The new logic in MyPhysics.LoadData
falls back to the call it made before: HkJobThreadPool()
But inside Havok (C++ code) they apparently changed it to default to a single thread in this case, so all the physics is running on a single thread (main thread).
Replaced an O(N*M) algorithm with one of better time complexity.
Improves the load time of servers with many grids. Potentially reduce lag as ships move around.
Cached the result of Reachable
calls, because they are very numerous
in case of grids with long conveyor networks (capital ships, production bases).
There is a separate cache per logical grid group.
Cache invalidation conditions:
- block added/removed to/from grid if the block has conveyor ports
- grid split/merge
- grid ownership change
- connector lock/unlock or config change
- grid added/remove to/from logical group
It eliminates most of the lag when players enter/leave cockpits or cryopods. It also reduces the conveyor overhead while loading large production grids.
It may have a slight impact on simple grids with short conveyor systems due to the additional overhead of building and using the cache for little benefit in that case, however this overhead should be negligible.
Fixed the HashSet corruption by using a MyConcurrentHashSet
.
Fixed the slow InScene getter by implementing the suggested fix.
Fixed the slow implementation by implementing the suggested fix.
Keen significantly changed MyDataReceiver.UpdateBroadcastersInRange
,
it is using a single MyUtils.ReuseCollection
. I consider this fixed,
but performance testing will be needed to confirm.
Original support ticket
Rate limited excessive logging from MyDefinitionManager.GetBlueprintDefinition
.
For example it caused 11000 of the "No blueprint with Id" messages logged every minute while players were running Isy's Inventory Manager PB script. In addition to the extra CPU load it risked running out of disk space if left unchecked.
Projected functional blocks are updated, which is a waste of time. Also due to bugs some of them can even function, for example projected welders can weld in creative mode if they are enabled in the blueprint.
In order to fixe these functional blocks have to be disabled on grids with no physics. These should only be the projected functional blocks. It happens only once when the functional block is added to the scene in order to avoid a constant CPU overhead.
Testing functionalBlock.CubeGrid?.Projector
instead would be more correct,
but it is not set when the projected block is added to the scene.
Setting NeedsUpdate to NONE does not work either. Solving it differently
would have more overhead.
This fix may have side-effects should a plugin provide physics-less subgrids. In such a case disable this fix and use the Multigrid Projector plugin to fix this specific case only for the welders in a different way.
This fix has the visual side-effect of all functional blocks showing up as disabled in the projection, so the players don't know in advance whether they will be enabled once welded. The fix does not affect the welded state, only the visual feedback. This applies only of this plugin is installed on the client side.
Keen reverted the default value of MyVoxelPhysicsBody.m_staticForCluster
to true in the 1.203.023 hotfix update.
Fixes for performance issues or bugs fixed by Keen in the regular public game version are removed from this page. Check the older versions of this document if you want to recall them.