Closed Bug 1680909 Opened 4 years ago Closed 4 years ago

Firefox floods the X server with XkbGetUpdatedMap requests when switching ibus input methods, stops responding to input

Categories

(Core :: Widget: Gtk, defect, P2)

78 Branch
x86_64
Linux
defect

Tracking

()

RESOLVED FIXED
85 Branch
Tracking Status
firefox-esr78 --- fixed
firefox85 --- fixed

People

(Reporter: da-wgh, Assigned: da-wgh)

Details

Attachments

(2 files)

I use Firefox 78.4.1esr, X server and ibus (provides input method switching) on Linux.

Every time I change the input method, Firefox bombards the X server with tens of thousands XkbGetUpdatedMap requests (see attached trace_procxkbgetmap_per_second.bt for reference how I obtained this data). This is the result of changing the input method just once:

@total1[uprobe:/usr/bin/X:ProcXkbGetMap]: 26036 # <- how many times the X server called this function
# how many times each process called this function (not all programs use libX11 to communicate with the X server, though)
@total2[uprobe:/usr/lib/libX11.so.6.3.0:XkbGetUpdatedMap, 3914837, alacritty]: 1
@total2[uprobe:/usr/lib/libX11.so.6.3.0:XkbGetUpdatedMap, 3916102, alacritty]: 1
@total2[uprobe:/usr/lib/libX11.so.6.3.0:XkbGetUpdatedMap, 3915717, alacritty]: 1
@total2[uprobe:/usr/lib/libX11.so.6.3.0:XkbGetUpdatedMap, 3862501, alacritty]: 1
@total2[uprobe:/usr/lib/libX11.so.6.3.0:XkbGetUpdatedMap, 3889826, parcellite]: 1
@total2[uprobe:/usr/lib/libX11.so.6.3.0:XkbGetUpdatedMap, 3916118, alacritty]: 1
@total2[uprobe:/usr/lib/libX11.so.6.3.0:XkbGetUpdatedMap, 3915869, alacritty]: 1
@total2[uprobe:/usr/lib/libX11.so.6.3.0:XkbGetUpdatedMap, 3412279, ibus-x11]: 2
@total2[uprobe:/usr/lib/libX11.so.6.3.0:XkbGetUpdatedMap, 3317212, Web Content]: 2
@total2[uprobe:/usr/lib/libX11.so.6.3.0:XkbGetUpdatedMap, 3315983, Web Content]: 2
@total2[uprobe:/usr/lib/libX11.so.6.3.0:XkbGetUpdatedMap, 3317601, Web Content]: 2
@total2[uprobe:/usr/lib/libX11.so.6.3.0:XkbGetUpdatedMap, 3412275, ibus-ui-gtk3]: 2
@total2[uprobe:/usr/lib/libX11.so.6.3.0:XkbGetUpdatedMap, 3318887, Web Content]: 2
@total2[uprobe:/usr/lib/libX11.so.6.3.0:XkbGetUpdatedMap, 3318394, Web Content]: 2
@total2[uprobe:/usr/lib/libX11.so.6.3.0:XkbGetUpdatedMap, 3317317, Privileged Cont]: 2
@total2[uprobe:/usr/lib/libX11.so.6.3.0:XkbGetUpdatedMap, 3315910, WebExtensions]: 2
@total2[uprobe:/usr/lib/libX11.so.6.3.0:XkbGetUpdatedMap, 3320616, Web Content]: 2
@total2[uprobe:/usr/lib/libX11.so.6.3.0:XkbGetUpdatedMap, 3316691, Web Content]: 2
@total2[uprobe:/usr/lib/libX11.so.6.3.0:XkbGetUpdatedMap, 3315863, Web Content]: 2
@total2[uprobe:/usr/lib/libX11.so.6.3.0:XkbGetUpdatedMap, 3315791, firefox]: 25953

When this happens, Firefox doesn't respond to text input. These calls take several seconds to complete, so I have to wait that time every time after input method switching to continue typing, which is pretty bad.

I have captured the Firefox call stack samples with perf, and this is how they look like:

 Children      Self  Command          Shared Object                             Symbol
-   91.12%     0.00%  firefox          /usr/lib64/firefox/libxul.so              0x7f504c6fb97d     l [.] XRE_main                     ◆
     XRE_main libxul.so                                                                                                                ▒
     XREMain::XRE_main libxul.so                                                                                                       ▒
     XREMain::XRE_mainRun libxul.so                                                                                                    ▒
     nsAppStartup::Run libxul.so                                                                                                       ▒
     nsBaseAppShell::Run libxul.so                                                                                                     ▒
     MessageLoop::Run libxul.so                                                                                                        ▒
   -→mozilla::ipc::MessagePump::Run libxul.so                                                                                          ▒
      -→91.12% NS_ProcessNextEvent libxul.so                                                                                           ▒
         -→nsThread::ProcessNextEvent libxul.so                                                                                        ▒
            -→90.85% nsBaseAppShell::OnProcessNextEvent libxul.so                                                                      ▒
               -→90.84% nsBaseAppShell::DoProcessNextNativeEvent libxul.so                                                             ▒
                  -→nsAppShell::ProcessNextNativeEvent libxul.so                                                                       ▒
                     - 90.83% g_main_context_iteration libglib-2.0.so.0.6600.2                                                         ▒
                        -→90.82% g_main_context_iterate.isra.0 libglib-2.0.so.0.6600.2                                                 ▒
                           -→90.59% g_main_context_dispatch libglib-2.0.so.0.6600.2                                                    ▒
                              - 90.56% 0x7f5051de72e1 libgdk-3.so.0.2404.18                                                            ▒
                                 - 0x7f5051e19aba libgdk-3.so.0.2404.18                                                                ▒
                                    - 90.56% 0x7f5051de769a libgdk-3.so.0.2404.18                                                      ▒
                                       - _gdk_x11_event_translator_translate libgdk-3.so.0.2404.18                                     ▒
                                          - 90.55% gdk_x11_display_translate_event libgdk-3.so.0.2404.18                               ▒
                                             - 90.55% g_signal_emit_by_name libgobject-2.0.so.0.6600.2                                 ▒
                                                - 90.55% g_signal_emit_valist libgobject-2.0.so.0.6600.2                               ▒
                                                   -→90.54% signal_emit_unlocked_R libgobject-2.0.so.0.6600.2                          ▒
                                                      -→89.83% g_closure_invoke libgobject-2.0.so.0.6600.2                             ▒
                                                         -→88.93% mozilla::widget::ResetBidiKeyboard libxul.so                         ▒
                                                            -→88.44% nsBidiKeyboard::Reset libxul.so                                   ▒
                                                               -→87.53% gdk_x11_keymap_have_bidi_layouts libgdk-3.so.0.2404.18         ▒
                                                                  +→54.87% XkbGetUpdatedMap libX11.so.6.3.0                            ▒
                                                                  +→29.65% XkbGetControls libX11.so.6.3.0                              ▒
                                                                  +→2.71% get_xkb libgdk-3.so.0.2404.18   

It's hard to tell which problem this actually is. i3 window manager also had similar problem with ibus, but it was alleviated with caching in xkbcommon (not yet released). https://github.com/i3/i3/issues/3924

mozilla::widget::ResetBidiKeyboard itself is being called so many times, but looking at the code it's not immediately obvious why. I'm open to assist with tracing and debugging.

When Firefox is freshly launched, the number of mozilla::widget::ResetBidiKeyboard is just several hundred per input method switch, and no visible lag occurs. The numbers becomes problematic only after Firefox is running long enough.

InitBySystemSettingsX11 seems to be called after the reset (since mInitialized is cleared). Could it be that g_signal_connect is not idempotent, and duplicate signal connections accumulate and cause this slowdown? I'll try to write a patch for that, and see if it helps.

When ibus input method is changed, Firefox reinitializes the KeymapWrapper
object, causing duplicate calls to g_signal_connect. If Firefox is running
long enough, duplicate handlers accumulate, and Firefox starts to barrage the
X server with XkbGetUpdatedMap/XkbGetControls calls, slowing the X server and
itself down.

A symptom of this problem is that after switching the input methods, Firefox
ignores the input for a while (up to several seconds).

Assignee: nobody → da-wgh

Thanks for the patch, will look at it.

Component: General → Widget: Gtk
Priority: -- → P2
Product: Firefox → Core

I'm running Firefox with the patch for several days, it certainly helps.

Pushed by stransky@redhat.com: https://hg.mozilla.org/integration/autoland/rev/1be2cf19dd20 Fix slowdown in X keyboard layout handling. r=stransky
Status: UNCONFIRMED → RESOLVED
Closed: 4 years ago
Resolution: --- → FIXED
Target Milestone: --- → 85 Branch

Hey, any chance of backporting it to ESR? It would be pretty annoying to live with this bug for extra half a year. The lag is severe enough, and ibus is default thing on many desktop environments.

Flags: needinfo?(stransky)

Comment on attachment 9191506 [details]
Bug 1680909 - Fix slowdown in X keyboard layout handling. r=stransky

ESR Uplift Approval Request

  • If this is not a sec:{high,crit} bug, please state case for ESR consideration: When X11 input method is changed (i.e. keyboard layout change) Firefox freezes and it's unusable. It's caused by redundant callbacks processed by Gtk.
  • User impact if declined:
  • Fix Landed on Version: 85.0
  • Risk to taking this patch: Low
  • Why is the change risky/not risky? (and alternatives if risky): Avoid to register more than one handler to "keys-changed" and "direction-changed" gtk callbacks. Should be without any risk.
  • String or UUID changes made by this patch: none
Flags: needinfo?(stransky)
Attachment #9191506 - Flags: approval-mozilla-esr78?

Comment on attachment 9191506 [details]
Bug 1680909 - Fix slowdown in X keyboard layout handling. r=stransky

Approved for 78.7esr.

Attachment #9191506 - Flags: approval-mozilla-esr78? → approval-mozilla-esr78+

Thanks!

You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: