Forum rules - please read before posting.

Optimizing save times when also saving screenshots

edited July 2024 in Technical Q&A

[Unity 2021.3.38f1 - AC v1.81.4]

Hi Chris!

I have very recently enabled screenshots in save files and have been experiencing slowdowns in save times ever since. Nothing incredibly frustrating, as we're talking about 1-2 seconds "hiccups", but it's much more noticeable during autosaves.

Even if I'd prefer to have screenshots for autosaves as well, I did try selecting "Except When Autosaving" to see if anything would happen. It would work fine on v1.80.4, but still produces a hiccup in v1.81.4. The screenshot itself is not showing in the Save and Load UIs, but it takes the same amount of time as if it was been saved.

I also tried changing the screenshot size, but I didn't experience any noticeable change in save times.

Regardless of the autosave issue, I was wondering if there was something more that could be done to increase save times. I already am saving using a separate thread and, in case it's important, all my scenes are Addressables.

Here are my current Saving settings in the Settings manager

Thanks a lot!

Comments

  • Too late to edit, but:

    "as if it was been saved"

    is an obvious typo!

  • The screenshot-recording process involves two steps: taking the screenshot itself, and writing it to disk.

    You can try using Unity's Profiler to work out exactly which process/function is causing the holdup (share screenshots if so), but if you've already tried reducing the size I'd say it's likely the former.

    What's your game's resolution, and does it take less time if you reduce it?

    It'd be worth trying the RenderTexture route - i.e. relying on a RenderTexture asset to record the screen with - as this asset type has a number of options you can play with that should affect the speed.

    To use it, create a new RT asset, add a new Camera (named e.g. Screenshot Cam) as a child of your MainCamera, and have it output to the RT. Then assign this asset in the Save screenshot texture field.

  • Sorry for the super late reply!

    I tried and I can't really notice major changes in saving times, I'm afraid.

    I tried both reducing the size of the RenderTexture (our basic resolution is 4096x2160, but I reduced the RT down to 960x540) and the Screenshot size factor in the Settings.

    Our biggest concern about this is mostly related to autosaves, which we would like to be as "silent" as possible.

    For what it's worth, I tried with a persistent camera with a script attached to it that, before saving, first grabs the size and position of the main camera then enables it, then turns it off after saving.

    Fearing it might be part of the issue, I tried not updating size and position and keeping it always enabled, but I didn't notice any difference.

  • What insight does the Profiler, with Deep Profile enabled, offer?

  • edited July 2024

    If needed I can send you the exported profiler .data file, but basically what I gather from it, according to this screenshot which shows the highest spike while saving \ autosaving:

    And although I now realize also Dialogue System has a huge role in this (which probably opens an entire new can of worms I'm not sure how I am going to tackle), AC's Save System still is "on top".

    Specifically, it seems that SystemFileHandler_SystemFile.GetSaveFile() is being called a lot (I have increased the number of saves to be fair), with the SystemFileHandler_SystemFile.LoadScreenshot() being the most "expensive" process in terms of GC and time required.

    In each SystemFileHandler_SystemFile.LoadScreenshot() the most expensive calls in terms of garbage collection are those to Texture2D..ctor() and File.ReadAllBytes(), while the most expensive in terms of time are those to Texture2D.Compress() and ImageConversion.LoadImage().

    One question that rises to mind, assuming I'm understanding what's happening here: is there a reason why, while saving, AC has to check out all of the already existing savefiles' screenshots?

    EDIT: these are full size images, so you should be able to open them in a separate window!

  • With this readout, I'd expect the process to be much faster if there were no other saves. Is this the case?

    The loading of all save data is a known bottleneck and something I'd like to address as part of the next major update. Currently, more data is loaded than strictly necessary so as to make sure that it's always on-hand, but there's plenty of room for optimisation that should make situations like this a lot faster.

  • edited August 2024

    I don't really appreciate any big change when reducing from 30 to 10 saves (as it was originally), I also removed the extra saves from the "Manage save-game files" menu.

    This is what happens on autosave, with 10 maximum save files, and without the RenderTexture:

    The ms only dropped ~400ms, it seems?

    For the sake of completion, these are the same results but with an actual RenderTexture:

    For what it's worth, although I have no actual data to prove it, I do remember the stutter not really happening when I had 10 saves before switching from v1.80.4 to v1.81.4.

  • Another thing that comes to mind. I might have once tried to increase the maximum saves up to 50 or more, but never used it so I then reverted back to 30.

    I'm thinking: maybe this works by considering only of the largest number that has been set, regardless of the current one?

  • It's actually a hard-coded value, currently. The "Max saves" field only affects how many saves can be written - it won't affect the reading of existing saves.

    If you open up AC's SaveFileHandler_SystemFile script, look for the following around line 377:

    protected virtual int MaxSaves { get return 50; } }
    

    Replace it with:

    protected virtual int MaxSaves { get { return Mathf.Min (50, KickStarter.settingsManager.maxSaves); } }
    

    That should cause the field to affect loading as well - does performance then improve?

  • Overall, I'm not experiencing much difference.

    • The amount of time required by SaveOperation.Update() is roughly the same.
    • The calls to SaveFileHandler_SystemFile.GetSaveFile() are greatly reduced
    • SaveSystem.GatherSaveFiles() roughly takes the same amount of time.

    Let me know if is there something else I can show you!

  • Try to reduce the "max saves" to its lowest value, i.e. 1.

    Ultimately, though, this is likely part of the optimisation issue I mentioned earlier - and will need to be improved as part of an update.

  • Yes, if I reduce them to 1 the performance is tangibly better


    Without the RenderTexture


    With the RenderTexture

  • Looks like Dialogue System is taking up the bulk of the GC Alloc / Time ms columns now - are those values only present in the same frame as AC saving?

  • I'm addressing this over on the DS forums too (https://www.pixelcrushers.com/phpbb/viewtopic.php?p=45434) and basically not really.

    Unless I'm wrong, it seems to me that anytime a Lua variable is checked \ updated, all of them are being checked again via observation, and that of course, happens during saves.

    So, yeah, I'm trying to address this from multiple sides :grimace:

  • Update: I applied the solution suggested by DialogueSystem developer and the difference is, as I said "night and day".

    In the same frame, this time the garbage collection and ms spent for DialogueSystemController.Update() are reduced to 0, so now most of the work is done by AC's SaveSystem.

    There are about 200-300ms total spent by AC and DS in the previous spike(s), on AC's side mostly for Remember scripts, but this is indeed huge progress!

    All of the above are tests made with max saves set to 30 again and I tried both with and without RT and the results are almost identical (~980-1000 ms).

    If I set the max saves to 1, I get about 80ms.

  • RememberDialogueSystem looks like it's the largest single Remember component.

    For the added time due to 30 saves: this will need to be addressed in an update, I'm hoping the next major release.

  • Thank you so much, as always! Looking forward to it!

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.