Do not throttle input in wayland event delivery
This merge request changes event delivery code so Wayland event delivery and MetaDisplay-level event management (i.e. everything that happens before deciding whether to let Clutter handle the event) is handled in an unthrottled fashion, while Clutter event delivery stays throttled at the display refresh rate.
This still does require pointer picking to happen on every event (as the actor underneath might change at any moment), this operation has been optimized by having ClutterPickContext return a "safe area" where the pointer is ensured to stay within the current actor, thus making pointer picking a more scarce operation (and almost none in some optimal cases like fullscreen windows, pointer locking, etc).
Other hotspots in frequent pointer updates have been identified and toned down. The target for these changes are 1000Hz gaming mice, and other high-rate input devices, in order to ensure that these get uncoalesced (and as fast as possible) to the clients, while performing decently.
Nothing has been done here to avoid potential wayland event queue overflows, as IIUC this is being worked on separately. Although I should probably also mention that this hasn't been seen in the wild during this work.
It's hard to compare before and after, since on one hand it is adding more things to do (event delivery frequency will increase on almost every device, varies between approx. 2x for touchpads to 16x for these gaming mice for the usual 60Hz update rate), but on the other hand it's alleviating some of that. Here's some perf
data to illustrate:
Before
# To display the perf.data header info, please use --header/--header-only options.
#
#
# Total Lost Samples: 0
#
# Samples: 33K of event 'cycles:u'
# Event count (approx.): 3419836782
#
# Children Self Command Shared Object Symbol
# ........ ........ .............. .................................. ............................................................................
#
49.23% 0.25% mutter libglib-2.0.so.0.6900.0 [.] g_main_loop_run
|
--48.97%--g_main_loop_run
g_main_context_iterate
|
|--31.59%--g_main_context_dispatch
| |
| --31.47%--g_main_dispatch
| |
| |--17.75%--meta_event_dispatch
| | |
| | --17.70%--dispatch_libinput
| | |
| | |--10.62%--process_events
| | | |
| | | --9.89%--process_event
| | | |
| | | --9.44%--process_device_event
| | | |
| | | --8.19%--meta_seat_impl_notify_relative_motion_in_impl
| | | |
| | | |--6.30%--new_absolute_motion_event
| | | | |
| | | | |--2.98%--meta_seat_impl_constrain_pointer
| | | | | |
| | | | | --2.91%--constrain_to_barriers
| | | | | |
| | | | | --2.89%--meta_barrier_manager_native_process_in_impl
| | | | | |
| | | | | --1.63%--clutter_seat_query_state
| | | | | |
| | | | | --1.29%--meta_seat_native_query_state
| | | | | |
| | | | | --0.97%--meta_seat_impl_query_state
| | | | |
| | | | |--0.68%--clutter_input_device_get_device_type
| | | | |
| | | | --0.65%--clutter_event_new
| | | |
| | | --1.42%--queue_event
| | | |
| | | --1.25%--_clutter_event_push
| | | |
| | | --0.65%--g_async_queue_push
| | | |
| | | --0.58%--g_async_queue_push_unlocked
| | | |
| | | --0.57%--g_queue_push_head
| | | |
| | | --0.51%--g_list_prepend
| | |
| | --6.48%--libinput_dispatch
| | |
| | --6.15%--evdev_device_dispatch
| | |
| | |--4.11%--evdev_device_dispatch_one
| | | |
| | | --4.01%--evdev_process_event
| | | |
| | | --3.69%--fallback_interface_process
| | | |
| | | --3.21%--fallback_handle_state
| | | |
| | | --3.00%--fallback_flush_relative_motion
| | | |
| | | |--1.58%--filter_dispatch
| | | | |
| | | | --1.48%--accelerator_filter_pre_normalized
| | | | |
| | | | --1.33%--accelerator_filter_generic
| | | | |
| | | | --1.31%--calculate_acceleration_factor
| | | | |
| | | | --0.69%--trackers_feed
| | | | |
| | | | --0.59%--device_float_get_direction
| | | | |
| | | | --0.58%--xy_get_direction
| | | |
| | | --1.19%--pointer_notify_motion
| | | |
| | | --0.68%--zalloc
| | |
| | --1.05%--libevdev_next_event
| |
| |--4.85%--clutter_source_dispatch
| | |
| | |--2.35%--clutter_do_event
| | | |
| | | --2.14%--_clutter_stage_queue_event
| | | |
| | | --1.34%--clutter_event_copy
| | | |
| | | --0.81%--clutter_event_new
| | | |
| | | --0.71%--g_malloc0_n
| | | g_malloc0
| | |
| | |--0.73%--clutter_event_get
| | | |
| | | --0.62%--g_async_queue_try_pop
| | | |
| | | --0.58%--g_async_queue_pop_intern_unlocked
| | |
| | --0.63%--clutter_event_free
| |
| |--2.26%--gdk_event_source_dispatch
| | |
| | --2.25%--gdk_display_get_event
| | |
| | --2.20%--_gdk_x11_display_queue_events
| | |
| | --1.79%--gdk_event_source_translate_event
| | |
| | --0.76%--_gdk_x11_event_translator_translate
| | |
| | --0.65%--gdk_x11_device_manager_xi2_translate_event
| |
| |--2.00%--frame_clock_source_dispatch
| | |
| | --1.98%--clutter_frame_clock_dispatch
| | |
| | --1.71%--handle_frame_clock_before_frame
| | |
| | --1.71%--_clutter_stage_process_queued_events
| | |
| | --1.36%--_clutter_process_event
| | |
| | --1.23%--_clutter_process_event_details
| | |
| | --1.07%--update_device_for_event
| | |
| | --1.05%--_clutter_stage_do_pick
| | |
| | --0.92%--_clutter_stage_do_pick_on_view
| | |
| | --0.69%--clutter_actor_pick
| | |
| | --0.62%--clutter_actor_continue_pick
| | |
| | --0.52%--clutter_actor_real_pick
| |
| |--1.97%--g_idle_dispatch
| | |
| | --1.67%--callback_idle
| | |
| | --1.66%--flush_callbacks
| | |
| | --1.52%--meta_kms_page_flip_data_flipped
| | |
| | --1.51%--page_flip_feedback_flipped
| | |
| | --1.37%--notify_view_crtc_presented
| | |
| | --1.18%--meta_onscreen_native_notify_frame_complete
| | |
| | --1.07%--_cogl_onscreen_notify_complete
| | notify_event
| | |
| | --1.06%--frame_cb
| | |
| | --0.98%--clutter_stage_view_notify_presented
| | |
| | --0.89%--clutter_stage_presented
| | |
| | --0.86%--g_signal_emit
| | g_signal_emit_valist
| | |
| | --0.55%--signal_emit_unlocked_R
| | |
| | --0.52%--g_closure_invoke
| |
| |--0.61%--meta_kms_fd_impl_source_dispatch
| | |
| | --0.61%--kms_event_dispatch_in_impl
| | |
| | --0.60%--meta_kms_impl_device_dispatch
| | |
| | --0.56%--drmHandleEvent
| | |
| | --0.55%--atomic_page_flip_handler
| |
| --0.56%--get_dispatch
|
|--8.19%--g_main_context_check
| |
| |--1.51%--g_source_iter_next
| | |
| | --0.55%--g_source_ref
| |
| |--0.72%--sleep_source_check
| |
| |--0.64%--gdk_event_source_check
| |
| |--0.57%--g_mutex_lock
| |
| --0.56%--clutter_source_check
|
|--6.23%--g_main_context_prepare
| |
| |--2.41%--gdk_event_source_prepare
| | |
| | --2.24%--gdk_check_xpending
| | |
| | --1.66%--XPending
| | |
| | --1.32%--_XEventsQueued
| | |
| | --1.06%--0x7f27a5a18c03
| | |
| | --1.01%--0x7f27a5a18a89
| |
| |--1.03%--g_source_iter_next
| |
| --0.56%--cogl_glib_source_prepare
|
--1.68%--g_main_context_poll
|
--0.95%--g_poll
|
--0.55%--poll@plt
After
# To display the perf.data header info, please use --header/--header-only options.
#
#
# Total Lost Samples: 0
#
# Samples: 29K of event 'cycles:u'
# Event count (approx.): 6778209184
#
# Children Self Command Shared Object Symbol
# ........ ........ .............. .................................. ...................................................................
#
50.41% 0.07% mutter libglib-2.0.so.0.6900.0 [.] g_main_context_iterate
|
--50.34%--g_main_context_iterate
|
|--39.76%--g_main_context_dispatch
| |
| --39.66%--g_main_dispatch
| |
| |--16.63%--clutter_source_dispatch
| | |
| | --15.64%--clutter_do_event
| | |
| | |--14.49%--_clutter_event_process_filters
| | | |
| | | --14.49%--event_callback
| | | |
| | | --14.47%--meta_display_handle_event
| | | |
| | | |--4.66%--meta_cursor_renderer_update_position
| | | | |
| | | | --4.14%--meta_cursor_renderer_update_cursor
| | | | |
| | | | |--1.66%--meta_cursor_renderer_update_stage_overlay
| | | | | |
| | | | | --1.19%--meta_stage_update_cursor_overlay
| | | | | |
| | | | | --1.18%--queue_redraw_for_overlay
| | | | | |
| | | | | --1.17%--queue_redraw_clutter_rect
| | | | | |
| | | | | --1.01%--clutter_actor_queue_redraw_with_clip
| | | | | |
| | | | | --0.62%--_clutter_actor_queue_redraw_full
| | | | | |
| | | | | --0.56%--clutter_stage_queue_actor_redraw
| | | | |
| | | | |--1.19%--meta_cursor_renderer_native_update_cursor
| | | | | |
| | | | | --0.59%--clutter_stage_schedule_update
| | | | |
| | | | --0.75%--meta_cursor_sprite_prepare_at
| | | | |
| | | | --0.75%--cursor_sprite_prepare_at
| | | | |
| | | | --0.61%--meta_wayland_surface_update_outputs
| | | |
| | | |--4.32%--meta_wayland_compositor_update
| | | | |
| | | | --4.05%--meta_wayland_seat_update
| | | | |
| | | | --3.90%--meta_wayland_pointer_update
| | | | |
| | | | --3.74%--repick_for_event
| | | | |
| | | | |--2.42%--meta_wayland_pointer_set_current
| | | | | |
| | | | | |--1.33%--g_signal_connect_data
| | | | | | |
| | | | | | --0.53%--signal_parse_name
| | | | | |
| | | | | --0.91%--g_signal_handler_disconnect
| | | | | |
| | | | | --0.58%--handler_unref_R
| | | | |
| | | | --0.76%--sync_focus_surface
| | | |
| | | |--2.24%--meta_wayland_compositor_handle_event
| | | | |
| | | | --2.13%--meta_wayland_seat_handle_event
| | | | |
| | | | --1.99%--meta_wayland_pointer_handle_event
| | | | |
| | | | --1.98%--handle_motion_event
| | | | |
| | | | --1.97%--notify_motion
| | | | |
| | | | --1.95%--default_grab_motion
| | | | |
| | | | --1.93%--meta_wayland_pointer_send_motion
| | | | |
| | | | --0.91%--wl_pointer_send_motion
| | | | |
| | | | --0.78%--wl_resource_post_event
| | | |
| | | |--0.89%--meta_window_handle_ui_frame_event
| | | | |
| | | | --0.79%--meta_ui_frame_handle_event
| | | | |
| | | | --0.76%--handle_motion_event
| | | |
| | | --0.69%--handle_idletime_for_event
| | | |
| | | --0.56%--meta_idle_manager_reset_idle_time
| | |
| | --0.75%--update_device_for_event
| | |
| | --0.55%--clutter_stage_pick_and_update_device
| |
| |--10.88%--gdk_event_source_dispatch
| | |
| | --10.84%--gdk_display_get_event
| | |
| | --10.68%--_gdk_x11_display_queue_events
| | |
| | |--8.22%--gdk_event_source_translate_event
| | | |
| | | |--4.08%--_gdk_x11_event_translator_translate
| | | | |
| | | | --3.79%--gdk_x11_device_manager_xi2_translate_event
| | | | |
| | | | |--1.80%--translate_axes
| | | | | |
| | | | | --0.99%--g_object_get
| | | | | |
| | | | | --0.98%--g_object_get_valist
| | | | |
| | | | --0.67%--_gdk_x11_moveresize_handle_event
| | | |
| | | |--1.82%--gdk_event_apply_filters
| | | | |
| | | | --1.38%--xevent_filter
| | | | |
| | | | --1.36%--meta_x11_display_handle_xevent
| | | |
| | | |--0.76%--gdk_event_source_get_filter_window
| | | | |
| | | | --0.65%--_gdk_x11_event_translator_get_window
| | | |
| | | --0.74%--gdk_event_free
| | |
| | --1.80%--_gdk_windowing_got_event
| | |
| | --0.73%--proxy_pointer_event
| |
| |--7.13%--meta_event_dispatch
| | |
| | --7.09%--dispatch_libinput
| | |
| | |--4.27%--process_events
| | | |
| | | --3.96%--process_event
| | | |
| | | --3.81%--process_device_event
| | | |
| | | --3.27%--meta_seat_impl_notify_relative_motion_in_impl
| | | |
| | | |--2.48%--new_absolute_motion_event
| | | | |
| | | | --1.01%--meta_seat_impl_constrain_pointer
| | | | |
| | | | --0.98%--constrain_to_barriers
| | | | |
| | | | --0.97%--meta_barrier_manager_native_process_in_impl
| | | |
| | | --0.64%--queue_event
| | | |
| | | --0.55%--_clutter_event_push
| | |
| | --2.62%--libinput_dispatch
| | |
| | --2.48%--evdev_device_dispatch
| | |
| | --1.64%--evdev_device_dispatch_one
| | |
| | --1.62%--evdev_process_event
| | |
| | --1.50%--fallback_interface_process
| | |
| | --1.32%--fallback_handle_state
| | |
| | --1.24%--fallback_flush_relative_motion
| | |
| | --0.64%--filter_dispatch
| | |
| | --0.61%--accelerator_filter_pre_normalized
| | |
| | --0.55%--accelerator_filter_generic
| | |
| | --0.54%--calculate_acceleration_factor
| |
| |--2.60%--frame_clock_source_dispatch
| | |
| | --2.59%--clutter_frame_clock_dispatch
| | |
| | --2.50%--handle_frame_clock_frame
| | |
| | --1.40%--_clutter_stage_window_redraw_view
| | |
| | --1.38%--meta_stage_native_redraw_view
| | clutter_stage_cogl_redraw_view
| | |
| | --1.37%--clutter_stage_cogl_redraw_view_primary
| | |
| | --0.76%--paint_stage
| | clutter_stage_paint_view
| | |
| | --0.73%--meta_stage_paint_view
| | |
| | --0.72%--clutter_stage_real_paint_view
| | |
| | --0.72%--clutter_stage_do_paint_view
| | |
| | --0.51%--clutter_actor_paint
| |
| --1.14%--g_idle_dispatch
| |
| --0.93%--callback_idle
| |
| --0.93%--flush_callbacks
| |
| --0.87%--meta_kms_page_flip_data_flipped
| |
| --0.87%--page_flip_feedback_flipped
| |
| --0.82%--notify_view_crtc_presented
| |
| --0.52%--meta_onscreen_native_notify_frame_complete
|
|--5.44%--g_main_context_check
| |
| |--1.81%--gdk_event_source_check
| | |
| | --1.67%--gdk_check_xpending
| | |
| | --1.49%--XPending
| | |
| | --1.40%--_XEventsQueued
| | |
| | --0.76%--0x7ff43a08fc03
| | |
| | --0.72%--0x7ff43a08fa89
| |
| --0.70%--g_source_iter_next
|
|--3.60%--g_main_context_prepare
| |
| |--1.06%--gdk_event_source_prepare
| | |
| | --0.99%--gdk_check_xpending
| | |
| | --0.73%--XPending
| | |
| | --0.63%--_XEventsQueued
| |
| --0.66%--g_source_iter_next
|
--0.96%--g_main_context_poll
|
--0.58%--g_poll
This is wiggling a 1000Hz mouse over an unsuspecting fullscreen client.