Skip to content

Use external message pump when calling MessageLoopWork (to fix bugs and improve performance) #246

Open
@cztomczak

Description

@cztomczak

Todo: Compare cefpython/src/subprocess/main_message_loop* files with cef/tests/shared/browser/main_message_loop* files. These files may have been changed after v66 update.

--

Using external message pump will improve performance, but it is also required to get rid of some bugs, like missing keyboard events on Mac/Windows reported on the CEF Forum in this topic, and this.

Examples that call cefpython.MessageLoopWork should implement external message pump.

In CEF there are two functions for running message loop:

  1. CefRunMessageLoop (cefpython.MessageLoop)
  2. CefDoMessageLoopWork (cefpython.MessageLoopWork) - for integrating into existing frameworks.

In CEF Python we use message loop work in most examples (only PyWin32 uses MessageLoop). According to CEF doc comments CefRunMessageLoop will always have the best performance.

Task 1: GTK example should call MessageLoop() on Linux

The pygtk_.py example could use cefpython.MessageLoop on Linux. CEF will call GTK's native loop and it should work good - tested in idriissha's fork. Currently cefpython.MessageLoopWork is called in a timer.

Update: gtk2.py example uses MessageLoop() by default and MessageLoopWork when --message-loop-timer flag is passed. I tried to use MessageLoop() in gtk3.py, but it didn't work.

Task 2: Use external message pump in other examples

There is issue 1805 in upstream CEF to improve support for a host owned message loop. It is now marked as Resolved. The CefSettings.external_message_pump option and CefBrowserProcessHandler::OnScheduleMessagePumpWork method already landed in master and in branch 2743. See this commit. You can pass the --external-message-pump flag to cefclient to test the new mode and see how it performs.

Example implementation in upstream cefclient:

  1. All platforms - main_message_loop_external_pump.cc
  2. Linux - main_message_loop_external_pump_linux.cc
  3. Windows - main_message_loop_external_pump_win.cc
  4. Mac - main_message_loop_external_pump_mac.mm

Doc comments for the new functionality:

  ///
  // Set to true (1) to control browser process main (UI) thread message pump
  // scheduling via the CefBrowserProcessHandler::OnScheduleMessagePumpWork()
  // callback. This option is recommended for use in combination with the
  // CefDoMessageLoopWork() function in cases where the CEF message loop must be
  // integrated into an existing application message loop (see additional
  // comments and warnings on CefDoMessageLoopWork). Enabling this option is not
  // recommended for most users; leave this option disabled and use either the
  // CefRunMessageLoop() function or multi_threaded_message_loop if possible.
  ///
  int external_message_pump;

  ///
  // Called from any thread when work has been scheduled for the browser process
  // main (UI) thread. This callback is used in combination with CefSettings.
  // external_message_pump and CefDoMessageLoopWork() in cases where the CEF
  // message loop must be integrated into an existing application message loop
  // (see additional comments and warnings on CefDoMessageLoopWork). This
  // callback should schedule a CefDoMessageLoopWork() call to happen on the
  // main (UI) thread. |delay_ms| is the requested delay in milliseconds. If
  // |delay_ms| is <= 0 then the call should happen reasonably soon. If
  // |delay_ms| is > 0 then the call should be scheduled to happen after the
  // specified delay and any currently pending scheduled call should be
  // cancelled.
  ///
  virtual void OnScheduleMessagePumpWork(int64 delay_ms) {}

  ///
  // Perform a single iteration of CEF message loop processing. This function is
  // provided for cases where the CEF message loop must be integrated into an
  // existing application message loop. Use of this function is not recommended
  // for most users; use either the CefRunMessageLoop() function or
  // CefSettings.multi_threaded_message_loop if possible. When using this function
  // care must be taken to balance performance against excessive CPU usage. It is
  // recommended to enable the CefSettings.external_message_pump option when using
  // this function so that CefBrowserProcessHandler::OnScheduleMessagePumpWork()
  // callbacks can facilitate the scheduling process. This function should only be
  // called on the main application thread and only if CefInitialize() is called
  // with a CefSettings.multi_threaded_message_loop value of false. This function
  // will not block.
  ///
  void CefDoMessageLoopWork();

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions