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
Tackle performance issues when accessing the preference file #5871
Conversation
The old implementation has some interesting consequences. As an example: if a user creates build templates then it can quickly consume your entire preference file. This would be fine if the table would be allocated once and then simply re-used. But that is not the case... in fact, it was re-created all over! When UI code retrieves a template it would call this function: fa/lua/ui/game/build_templates.lua Lines 69 to 71 in d0d62d8
In the old implementation it would then use build_templates = {
-- (...) other templates
{
templateData = {
32,
32,
{
'ueb0102',
16257,
0,
0
},
{
'ueb0102',
16323,
8,
8
},
{
'ueb0102',
16477,
16,
16
},
{
'ueb0102',
16491,
24,
24
},
{
'ueb0102',
16543,
16,
0
},
{
'ueb0102',
16597,
24,
8
},
{
'ueb0102',
16611,
0,
16
},
{
'ueb0102',
16663,
8,
24
},
{
false,
16680,
0,
8
},
{
'ueb1301',
16835,
8,
0
},
{
'ueb1301',
16975,
24,
0
},
{
'ueb1301',
17156,
24,
16
},
{
'ueb1301',
17322,
16,
24
},
{
'ueb1301',
17517,
0,
24
},
{
'ueb4202',
17878,
17,
7
},
{
'ueb1101',
17997,
11,
19
},
{
'ueb1101',
18033,
11,
17
},
{
'ueb1101',
18044,
11,
15
},
{
'ueb1101',
18051,
11,
13
},
{
'ueb1101',
18074,
9,
13
},
{
'ueb1101',
18099,
7,
13
},
{
'ueb1101',
18205,
13,
5
},
{
'ueb1101',
18241,
13,
7
},
{
'ueb1101',
18253,
13,
9
},
{
'ueb1101',
18290,
13,
11
},
{
'ueb1101',
18306,
17,
11
},
{
'ueb1101',
18313,
19,
11
}
},
name = 'Air Factory',
icon = 'ueb0102'
},
-- (...) other templates
}, This is a single entry with just 27 structures in it. It is a little over a kilobyte worth of data. Considering that some people even have entire wall-based paintings in their templates this can easily represent up to dozens, if not hundreds of kilobytes worth of data! And in the old implementation all of this data would be unique data, recreated each time the user build templates are retrieved! As a few humble examples:
This is a subtle one, because when a unit in the selection dies then the selection changes too. During large battles, this would trigger constantly!
Note that this is on top of (1). We'd allocate two instances of the user templates table when this option is enabled.
Each cycle would recreate the user templates table from scratch! All of this is bad enough - but funny enough the implementation of (2) actually relies on the templates being unique each time the selection changes, or it crashes. Which is odd - why would you rely on data that may be dozens if not hundreds of kilobytes to be unique each time a selection changes? 😃 Long story short - this is a massive garbage dumb for players that use templates. I barely use templates and the table is already 17 kilobytes:
Glad to have found this garbage dumb. It is an amazing candidate to generate stutters as you play the game. |
The original developers wrote an interface to make it easier to interact with the preference file. You can find it in Lines 89 to 97 in d0d62d8
This function is often used to update the preference file. It makes it easier to update a specific profile. Knowing what we know about Yes... Uhuh! That is right - for each time we update a field in the preference file via this function we casually deep-copying all the user profiles, including all of their content. Then we update a field. And then we update all the user profiles. For my preference file, this means it is allocating 73 kilobytes for all the profiles, then updates a field and then it effectively throws the table away again. And it would do this for every field we update. And we update fields often 😃 , both while playing (hotkeys, etc) but especially often when we're in the lobby. With the new implementation, the lobby is a lot faster. The garbage collector is on 🔥 , but we're fine right! |
It no longer changes the templates destructively. It will try to convert the units, and if it fails it simply skips the template.
@4z0t / @gordenwunderlich would either if you be available to test the hotbuild alternative implementation for all-faction templates? And yes - this is not 'do not repeat yourself' proof, but the goal of this PR is not to fix the code style issue. It is to fix a gigantic garbage collection problem. |
The preference file can be accessed with
GetPreference
, updated withSetPreference
and written to the disk withSavePreferences
. These functions have some interesting side effects:Todo: