-
Notifications
You must be signed in to change notification settings - Fork 29
Reduce Craft Browser Open and Search Times #284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reduce Craft Browser Open and Search Times #284
Conversation
|
I'll be interested to see how this performs compared to the custom craft browser dialog I created in BDArmory's version of the vessel spawner mod where craft meta-data is cached between uses (it's cleared when the "BDA Vessel Mover" window is hidden), which allows for an effectively instant new dialog when used multiple times. KSP's built-in craft browser dialog seems to start from fresh each time the dialog is opened, which causes a significant delay when used multiple times in a scene. Additionally, filtering is applied immediately whenever the selection filter or craft list is updated as it's just filtering a cached list of strings, which doesn't appear to give any noticable delay. |
|
Caching loadmeta files (or rather the I tentatively remember the majority of the time spent filtering is calling I'm trying to avoid modding at the moment, but those are my thoughts. |
|
Yeah, BDA's custom craft browser is using IMGUI, so it's simply a matter of filtering the list of strings and then only drawing the appropriate entries. No need for messing with game objects. In any case, I look forward to this actually being released (not just a pre-release), so I can update through CKAN. |
Problem
There's a long freeze whenever you open the craft browser that's proportional to the number of craft. You'd think it was because the game is reading the .loadmeta files for each craft, but it's also proportional to the overall number of parts, so it must be reading the craft files themselves to an extent.
dotTrace (release player, with KSPCF) shows that, from the start function of
CraftBrowserDialog, significantly more time is spent inCraftEntry.GetThumbURLthan is spent actually reading the .loadmeta.This is entirely due to
ShipConstruction.CheckCraftFileType, called once per craft, which performs aConfigNode.Loadon the craft file itself. It does this solely so it can work out the filename to find for the thumbnail (e.g. default_SPH_Miner.png) by looking at thetypefield in the craft file (SPH or VAB).ShipConstruction.CheckCraftFileTypeis also called in theWrongVesselTypeForLaunchSitepre-flight check when you launch a vessel.BuildPlayerCraftListcan be called twice in one frame, and once more in the following frame, depending on the context, but this doesn't always rebuild the craft list, only the UI. The unnecessary work still slows the open time down by about 30%.The time is takes to search by name also scales very badly, proportional to the number of craft. The list is filtered by
CraftSearch.SearchRoutine, which yields for a frame after checking each entry, regardless of the elapsed frame time.Changes
CheckCraftFileTypeby avoiding loading the whole craft file, instead only checking the file path. Thetypefield in the loadmeta could be used here if it turns out that the path does not always contain the facility name, although if the loadmeta file doesn't exist the craft file would need to be read for it to be generated.CraftBrowserDialogfrom rebuilding the craft list twice in a frame.Debug.Logwhen the thumbnail is not found.CraftSearch.SearchRoutineto prevent the coroutine from yielding for a frame on each entry. Instead use an 8 ms budget, and make some small optimisations such as avoiding the use ofGetComponent.Profiling
81 craft files totalling 75 MB
Release player, KSPCF including ConfigNodePerf
BuildPlayerCraftListBefore: 2,674 msBuildPlayerCraftListAfter: 271 msFlame Graph Before:
Flame Graph After:
Opening the craft browser is still not fast enough to feel responsive with this many craft. Maybe in future the entry creation could be put into a coroutine that populates the list over several frames. I did investigate multithreading the code using
Parallel.ForEachto create eachCraftProfileInfo(read the loadmeta files), but ConfigNodePerf isn't intended to be thread safe.