Pidgeot / python-lnp

Cross-platform re-implementation of the Lazy Newb Pack launcher.
ISC License
65 stars 10 forks source link

Modifying any settings takes around 1 second of CPU time (OS X?) #104

Closed Pidgeot closed 4 years ago

Pidgeot commented 4 years ago

Changing a setting (by toggling a button or after clicking "OK" in an entry dialog) causes the program to consume an entire CPU core for around a second and locks up the UI entirely.

[Issue created by lethosor: 2015-12-30] [Last updated on bitbucket: 2016-01-16]

[Comment created by Pidgeot: 2016-01-16] Disable entry change callbacks during UI update (fixes #105)

→ <>

[Comment created by Pidgeot: 2016-01-16] The issue seems to be the UI updating itself with values. This causes the text boxes to change... and when they change, they each request settings to be saved.

I've fixed that now by disabling that particular callback during the UI update process. This should bring the performance back to acceptable levels; if it's not sufficient, please reopen.

[Comment created by Dricus: 2016-01-01] I've added some logging to settings.py, and the code for saving settings appears to be incredibly inefficient. After every change in the GUI, and right after selecting a DF version on startup, every settings file gets saved 12 times! It looks like this has something to do with the GUI handling code, because the Qt version saves every settings file only once.

This change:

    def write_settings(self):
        """Write all settings to their respective files."""
        for files in self.in_files:
            for filename in files:
                print("Writing " + filename)
                self.update_file(filename, self.in_files[files])

Results in the following output:

Writing .\Dwarf Fortress 0.40.24\data\init\init.txt
Writing .\Dwarf Fortress 0.40.24\data\init\d_init.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_layer.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_mineral.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_soil.txt
Writing .\Dwarf Fortress 0.40.24\data\init\init.txt
Writing .\Dwarf Fortress 0.40.24\data\init\d_init.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_layer.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_mineral.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_soil.txt
Writing .\Dwarf Fortress 0.40.24\data\init\init.txt
Writing .\Dwarf Fortress 0.40.24\data\init\d_init.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_layer.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_mineral.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_soil.txt
Writing .\Dwarf Fortress 0.40.24\data\init\init.txt
Writing .\Dwarf Fortress 0.40.24\data\init\d_init.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_layer.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_mineral.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_soil.txt
Writing .\Dwarf Fortress 0.40.24\data\init\init.txt
Writing .\Dwarf Fortress 0.40.24\data\init\d_init.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_layer.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_mineral.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_soil.txt
Writing .\Dwarf Fortress 0.40.24\data\init\init.txt
Writing .\Dwarf Fortress 0.40.24\data\init\d_init.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_layer.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_mineral.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_soil.txt
Writing .\Dwarf Fortress 0.40.24\data\init\init.txt
Writing .\Dwarf Fortress 0.40.24\data\init\d_init.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_layer.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_mineral.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_soil.txt
Writing .\Dwarf Fortress 0.40.24\data\init\init.txt
Writing .\Dwarf Fortress 0.40.24\data\init\d_init.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_layer.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_mineral.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_soil.txt
Writing .\Dwarf Fortress 0.40.24\data\init\init.txt
Writing .\Dwarf Fortress 0.40.24\data\init\d_init.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_layer.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_mineral.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_soil.txt
Writing .\Dwarf Fortress 0.40.24\data\init\init.txt
Writing .\Dwarf Fortress 0.40.24\data\init\d_init.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_layer.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_mineral.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_soil.txt
Writing .\Dwarf Fortress 0.40.24\data\init\init.txt
Writing .\Dwarf Fortress 0.40.24\data\init\d_init.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_layer.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_mineral.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_soil.txt
Writing .\Dwarf Fortress 0.40.24\data\init\init.txt
Writing .\Dwarf Fortress 0.40.24\data\init\d_init.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_layer.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_mineral.txt
Writing .\Dwarf Fortress 0.40.24\raw\objects\inorganic_stone_soil.txt

[Comment created by PeridexisErrant: 2016-01-14] The callback graph in #86 may be pretty useful for this; I had a go at tracing what happens but didn't really get anywhere - there's nothing that stood out as outrageous, anyway.

Also played around with caching in various places, only writing changed files, etc, with no perceptible difference. It looks to me like it's basically down to a combination of DFRaw being expensive, and something in the TKGUI calling it way more often than it should. For that matter, on startup there's no reason to be saving out settings at all...

[Comment created by txtsd: 2015-12-31] Similar large CPU spike on linux. GUI freezes while it happens too.

@lethosor Can you profile @Dricus's qt-gui branch too, please? The GUI freezes for a similar amount of time, but only on first interaction.

[Comment created by lethosor: 2015-12-30] Here's the result of running launch.py with cProfile (python -m cProfile -s tottime launch.py) and toggling the invaders setting 10 times. It looks like dfraw-related code is using a lot of CPU time (e.g. at least 400k calls to find_first() per toggle, which is also called around 400k times on startup).