mike-fabian / ibus-typing-booster

ibus-typing-booster is a completion input method for faster typing
https://mike-fabian.github.io/ibus-typing-booster/
Other
228 stars 16 forks source link

Jumps to 10% CPU usage when opening OSK and 20% when closing OSK #425

Closed PhilDevProg closed 1 year ago

PhilDevProg commented 1 year ago

Describe the bug When I open the GNOME OSK the CPU usage of ibus-typing-booster jumps to 10% and when closing it jumps to even 20%, sometimes even 25%

To Reproduce Steps to reproduce the behavior:

  1. Open GNOME OSK
  2. See 10% CPU usage of python3 process
  3. Close GNOME OSK
  4. See 20% CPU usage of python3 process

Expected behavior Not using 10/20% of my CPU

Screenshots or videos Bildschirmaufzeichnung vom 2023-02-17, 15-21-05.webm

ibus-typing-booster version? 2.21.0

ibus version? IBus 1.5.27

Distribution and version? Fedora 37

Desktop and version? GNOME 43.2

Xorg or Wayland? Wayland

Additional context My CPU is an Intel Core i3-10100Y with 4 cores.

mike-fabian commented 1 year ago

Looking at your video, it seems to me that it is only a brief moment or more CPU activity when opening and closing OSK.

OSK activates typing booster automatically when typing booster is not yet active to be able to show word completions on buttons at the top of OSK.

If typing booster is already enabled, i.e. if typing booster is selected in the Gnome panel and then OSK is opened and closed, this should not happen. In that case, typing booster is used as is with the current settings.

But if typing booster is not enabled and the current input engine starts with xkb:, then OSK enables typing booster automatically. When doing that, it remembers the current settings of typing booster and sets new settings:

When OSK is closed, it sets typing booster to the settings OSK remembered when it was opened.

Here is the code in gnome-shell doing this for OSK:

https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/misc/ibusManager.js#L355

    setCompletionEnabled(enabled, callback) {
        /* Needs typing-booster available */
        if (enabled && !this._engines.has(TYPING_BOOSTER_ENGINE))
            return false;
        /* Can do only on xkb engines */
        if (enabled && !this._currentEngineName.startsWith('xkb:'))
            return false;

        if (this._oskCompletion === enabled)
            return true;

        this._oskCompletion = enabled;
        let settings =
            new Gio.Settings({schema_id: IBUS_TYPING_BOOSTER_SCHEMA});

        if (enabled) {
            this._preOskState = {
                'engine': this._currentEngineName,
                'emoji': settings.get_value(KEY_EMOJIPREDICTIONS),
                'langs': settings.get_value(KEY_DICTIONARY),
                'completion': settings.get_value(KEY_INLINECOMPLETION),
                'inputMethod': settings.get_value(KEY_INPUTMETHOD),
            };
            settings.reset(KEY_EMOJIPREDICTIONS);

            const removeEncoding = l => l.replace(/\..*/, '');
            const removeDups = (l, pos, arr) => {
                return !pos || arr[pos - 1] !== l;
            };
            settings.set_string(
                KEY_DICTIONARY,
                GLib.get_language_names().map(removeEncoding)
                    .sort().filter(removeDups).join(','));

            settings.reset(KEY_INLINECOMPLETION);
            settings.set_string(KEY_INPUTMETHOD, 'NoIME');
            this._setEngine(TYPING_BOOSTER_ENGINE, callback);
        } else if (this._preOskState) {
            const {engine, emoji, langs, completion, inputMethod} =
                  this._preOskState;
            this._preOskState = null;
            this._setEngine(engine, callback);
            settings.set_value(KEY_EMOJIPREDICTIONS, emoji);
            settings.set_value(KEY_DICTIONARY, langs);
            settings.set_value(KEY_INLINECOMPLETION, completion);
            settings.set_value(KEY_INPUTMETHOD, inputMethod);
        }
        return true;
    }

Changing these typing booster settings takes some CPU time, almost all of that time is used for changing the dictionaries. For example, let’s assume typing booster had the dictionaries de_DE,fr_FR when OSK was closed, and when OSK opens it sets the dictionaries to en_GB. That means /usr/share/hunspell/en_US.dic has to be opened and parsed and that has 48428 lines:

$ wc /usr/share/hunspell/en_US.dic  
 48428  48428 539608 /usr/share/hunspell/en_US.dic

Then, when OSK closes, it needs to open and parse the German and French dictionaries again:

$ wc /usr/share/hunspell/{de_DE,fr_FR}.dic

  75782   75852 1101641 /usr/share/hunspell/de_DE.dic
  82599   82599 1126134 /usr/share/hunspell/fr_FR.dic
 158381  158451 2227775 total

so it needs to parse 158381 lines again.

That is what is taking the CPU time.

Maybe Typing booster should not throw away already opened and parsed dictionary objects when the dictionary settings are changed but keep them around in some sort of cache for later in case the same dictionary settings are used again in the same session. Thinking about this.

mike-fabian commented 1 year ago

Fix included in https://github.com/mike-fabian/ibus-typing-booster/releases/tag/2.21.4

The very first time when OSK opens, it still uses CPU to load the different dictionaries used in OSK. But when closing OSK it is already fast because the dictionaries used without OSK have been remembered and are reused. When OSK is opened again, it is also fast because the dictionary/dictionaries used in OSK are now also remembered and reused.

mike-fabian commented 1 year ago

Update for Fedora 37: https://bodhi.fedoraproject.org/updates/FEDORA-2023-c025fe0e63