After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 568160 - Gnome Settings daemon causes high CPU usage with an expensive call
Gnome Settings daemon causes high CPU usage with an expensive call
Status: RESOLVED FIXED
Product: gnome-desktop
Classification: Core
Component: libgnome-desktop
git master
Other Linux
: Normal major
: ---
Assigned To: Federico Mena Quintero
Desktop Maintainers
: 574931 (view as bug list)
Depends on:
Blocks: randr-tracker
 
 
Reported: 2009-01-18 10:43 UTC by Alberto Milone
Modified: 2009-04-08 18:20 UTC
See Also:
GNOME target: ---
GNOME version: 2.25/2.26


Attachments
Patch to fix the bug (1.74 KB, patch)
2009-01-18 10:44 UTC, Alberto Milone
none Details | Review
Patch to fix the bug at compilation time (699 bytes, patch)
2009-01-19 13:24 UTC, Alberto Milone
none Details | Review
Patch to fix the bug at compilation time based on randr.h (496 bytes, patch)
2009-01-19 16:15 UTC, Alberto Milone
none Details | Review
ignore output property changes (345 bytes, patch)
2009-01-21 09:20 UTC, Alberto Milone
reviewed Details | Review
Output properties changes call the least expensive function. (2.79 KB, patch)
2009-03-19 10:36 UTC, Alberto Milone
none Details | Review
Final patch (5.55 KB, patch)
2009-03-20 16:44 UTC, Alberto Milone
none Details | Review
Final version of the patch (6.63 KB, patch)
2009-03-24 11:38 UTC, Alberto Milone
none Details | Review
/gnome-desktop-bgo568160-randr-avoid-reprobing.diff (7.76 KB, patch)
2009-04-08 18:19 UTC, Federico Mena Quintero
committed Details | Review

Description Alberto Milone 2009-01-18 10:43:29 UTC
According to the following bug report the gnome settings daemon causes high CPU usage with libxrandr 1.2.99.2 or higher:
https://bugs.edge.launchpad.net/ubuntu/+source/libxrandr/+bug/307306

The problem is that it calls XRRGetScreenResources() (which is an rather expensive call) instead of XRRGetScreenResourcesCurrent() which is cheaper and doesn't cause hardware to be reprobed.

While I agree that listening to events which represent changes in screen, crtc, output properties is ideal, calling XRRGetScreenResources each time something (e.g. the backlight) changes is really expensive and (if RandR 1.3 is available) this can be avoided.
Comment 1 Alberto Milone 2009-01-18 10:44:55 UTC
Created attachment 126677 [details] [review]
Patch to fix the bug

This patch will detect the version of RandR and use XRRGetScreenResourcesCurrent when available.
Comment 2 Vincent Untz 2009-01-19 12:23:59 UTC
Hrm, if the API is only available in 1.3, then your patch won't compile with xrandr 1.2. Or am I missing something?
Comment 3 Alberto Milone 2009-01-19 12:29:17 UTC
It will compile. If RandR 1.2 is used then the old behaviour (XRRGetScreenResources) is preserved.
Comment 4 Alberto Milone 2009-01-19 12:31:22 UTC
The RandR version check takes place at runtime.
Comment 5 Alberto Milone 2009-01-19 13:24:03 UTC
Created attachment 126752 [details] [review]
Patch to fix the bug at compilation time

As Vincent pointed out on IRC, compilation will fail if RandR 1.3 is not available since the new function doesn't exist in 1.2.

This new patch is even simpler and checks the availability of RandR 1.3 at compilation time
Comment 6 Vincent Untz 2009-01-19 14:28:19 UTC
Where is RANDR_13_INTERFACE defined? I don't see it in headers from http://cgit.freedesktop.org/xorg/proto/randrproto/tree/
Comment 7 Alberto Milone 2009-01-19 16:15:49 UTC
Created attachment 126771 [details] [review]
Patch to fix the bug at compilation time based on randr.h

This patch relies on randr.h i.e. on the RandR procol rather than on the
xserver itself. This will prevent us from adding the xserver development
libraries as build dependencies (thus preserving the previous behaviour).
Comment 8 Vincent Untz 2009-01-19 16:43:53 UTC
Thanks, committed!
Comment 9 Peter Clifton 2009-01-20 15:03:01 UTC
You still need to check the version of the extension at runtime, otherwise you will fail if communicating with an older server.
Comment 10 Alberto Milone 2009-01-21 09:20:31 UTC
Created attachment 126905 [details] [review]
ignore output property changes

This patch written by Peter Clifton makes sure that output property changes (e.g. in the backlight) don't trigger XRRGetScreenSizeRange, thus reducing the amount of times this expensive function is called.
Comment 11 Federico Mena Quintero 2009-01-26 20:29:09 UTC
But does using XRRGetScreenResourcesCurrent() actually work?

Note that the Display capplet in gnome-control-center has a "detect displays" button which calls gnome_rr_screen_refresh():

  gnome_rr_screen_refresh()
    screen_update()
      screen_info_new()
        fill_out_screen_info()
          XRRGetScreenResourcesCurrent()

The capplet expects that gnome_rr_screen_refresh() will yield "the latest refreshed status", not "the last known status", so that the capplet will be able to display accurate information about the monitors that are plugged in.

(Remember that we have a "Detect Displays" command precisely because we don't get hotplug notifications in many situations, so the user must be able to trigger a "detect everything now" command.)

We may need to make a distinction between "get me the last known status", suitable for gnome_rr_screen_new(), and "get me the refreshed status", for gnome_rr_screen_refresh().

CCing Søren to see if he has something to say about the intended API with RANDR 1.3 in the picture.
Comment 12 Peter Clifton 2009-01-26 21:32:38 UTC
Hmm, I take your point.

The distinction between retrieving explcitly probed costly information, and performing costly probes from within a change notification callback should probably be made in the code.
Comment 13 Alberto Milone 2009-01-26 21:34:27 UTC
Federico: it works well here. I suspect that XRRGetScreenSizeRange() (called in fill_out_screen_info) does (or causes) hardware probing (since it's a rather expensive call).
Comment 14 Soren Sandmann Pedersen 2009-01-28 17:18:33 UTC
The way GnomeRR works, it is never useful to call XRRGetScreenResourcesCurrent(). Either a reprobe is necessary, or the existing information in GnomeRRScreen is still valid.

RandR is designed so that you are supposed to call XRRGetScreenResources() whenever you get a change notification. It may make sense to move that call to an idle handler since you often get more than one at the same time.
Comment 15 Peter Clifton 2009-01-28 17:39:33 UTC
I really don't think that is true any more.

The change notifications should actually carry the information you need, and if not, the Xserver notifying you _of_ the change, already knows the required config, hence XRRGetScreenResourcesCurrent() _is_ appropriate.
Comment 16 Matthias Clasen 2009-02-20 03:20:37 UTC
This change breaks the Detect Monitors button
Comment 17 Alberto Milone 2009-02-20 09:55:41 UTC
Yes, now that the bug in libxrandr has been fixed I think this patch can be reverted. I agree with Federico though that it would be wise to make a distinction between getting the last known status and reprobing hardware.
Comment 18 Alberto Milone 2009-03-19 10:36:35 UTC
Created attachment 130951 [details] [review]
Output properties changes call the least expensive function.

The attached function simply distinguishes between changes in output properties and other RR events. When the former take place, the least expensive function is called.

If you agree with my changes I can work on it so as to check the version of RandR both at runtime and at compilation time.

Let me know.

NOTE: the following bug report seems to be a duplicate of this one:
http://bugzilla.gnome.org/show_bug.cgi?id=574931
Comment 19 Federico Mena Quintero 2009-03-19 18:48:52 UTC
*** Bug 574931 has been marked as a duplicate of this bug. ***
Comment 20 Federico Mena Quintero 2009-03-19 18:59:50 UTC
(In reply to comment #18)

> The attached function simply distinguishes between changes in output properties
> and other RR events. When the former take place, the least expensive function
> is called.

Nice!  Can you please make some stylistic changes:

* Call the extra argument "needs_reprobe" instead of "is_cheap", to make it self-explanatory, and of course reverse the test in fill_out_screen_info().

* The convention is that a GError argument to a function is always passed at the end.  Put the needs_reprobe argument before the GError.

* Can you pass the "-p" option to diff so it will put function names in each hunk?

* In screen_on_event(), can't we handle *all* events with needs_reprobe=FALSE?

* We may need to do something to avoid XRRGetScreenSizeRange().  Can we call it only when the updated timestamp changes, or something like that?

> If you agree with my changes I can work on it so as to check the version of
> RandR both at runtime and at compilation time.

Yes, we need that.

Comment 21 Alberto Milone 2009-03-20 15:42:35 UTC
>
> * In screen_on_event(), can't we handle *all* events with
> needs_reprobe=FALSE?
 
I would rather not, otherwise if something more important than output properties changes and we don't notice it, thus not calling RRGetScreenInfo again (etc.), weird things can happen.
 
>
> * We may need to do something to avoid XRRGetScreenSizeRange().  Can we
> call it only when the updated timestamp changes, or something like that?
>
 
Yes, that call is pretty expensive too. I think we can skip it if "needs_reprobe == FALSE".
 
As I said above, it's still good to keep it if something (other than output properties) changes.
 
I'll attach a new patch soon.
Comment 22 Alberto Milone 2009-03-20 16:44:59 UTC
Created attachment 131041 [details] [review]
Final patch

I hope the attached patch matches what Federico suggested. If it doesn't, just let me know and I'll rewrite it.
Comment 23 Alberto Milone 2009-03-20 16:59:51 UTC
Actually, now that I think about it, it's not such a great idea to check the version of RandR for each event.

I'll rewrite the patch.
Comment 24 Federico Mena Quintero 2009-03-20 19:09:12 UTC
(In reply to comment #21)
> >
> > * In screen_on_event(), can't we handle *all* events with
> > needs_reprobe=FALSE?
> 
> I would rather not, otherwise if something more important than output
> properties changes and we don't notice it, thus not calling RRGetScreenInfo
> again (etc.), weird things can happen.

I mean, when the X server sends a RANDR event, does it also have knowledge of the new state of the outputs?  I would assume so, otherwise it wouldn't have sent the event ;)  Can you check the X sources to see if this is the case?  If the server already knows the new state, then we can call XRRGetScreenResourcesCurent() instead of the expensive call when we get an event.
Comment 25 Alberto Milone 2009-03-23 15:41:40 UTC
I have tried to distinguish between the different events supported by RandR and I've noticed that the RRScreenChangeNotify event (i.e. the one that should be triggered when you plug in or unplug outputs) is triggered only when you explicitly probe hardware.

I talked to ajax and keithp and they told me that "they're hooking up interrupt-driven hotplug in KMS, but it isn't working yet" and that kind of event is "entirely dependent on the driver to wire up interrupts for output changes.  which none of them do yet."

When all this is ready we could safely use XRRGetScreenResourcesCurrent() (or XRRGetScreenResources) when we receive a RRScreenChangeNotify event. For all the rest (i.e. for devices that you don't get real hotplug for like some vga or tv ports) users will have to click on the "Detect monitors" button so as to probe hardware manually.

In conclusion all we do at the moment is simply get RROutputPropertyNotify (mainly because of changes in the "BACKLIGHT" property) when for example we unplug or plug in the AC cable of a laptop, which is really not something for which we should call XRRGetScreenResources().

In my opinion, if we really want to make this future-proof (and fix this bug too) we should do the following:
1) intercept RRScreenChangeNotify events and, only in this case, call XRRGetScreenSizeRange() and either XRRGetScreenResources() or XRRGetScreenResourcesCurrent().
2) in case of other events it would be more than enough to call XRRGetScreenResourcesCurrent()
Comment 26 Alberto Milone 2009-03-24 11:38:37 UTC
Created attachment 131247 [details] [review]
Final version of the patch

The attached patch should finally fix this bug and make gnome-desktop future-proof (waiting for KMS and hotplug events).

Please review it and let me know if there's something that you would like to see changed.
Comment 27 Federico Mena Quintero 2009-04-08 18:19:47 UTC
Created attachment 132356 [details] [review]
/gnome-desktop-bgo568160-randr-avoid-reprobing.diff

This is the patch I committed; it is essentially Alberto's patch with some stylistic changes.

2009-04-08  Federico Mena Quintero  <federico@novell.com>

	http://bugzilla.gnome.org/show_bug.cgi?id=568160 - Use
	XRRGetScreenResourcesCurrent() if available (i.e. we were compiled
	with RANDR 1.3 and it is actually available at runtime), when we
	only need to fetch the current RANDR status.  Use
	XRRGetScreenResources() as usual when we do need to re-probe.
	Patch by Alberto Milone <albertomilone@alice.it>, with minor
	modifications:

	* gnome-rr.c (fill_out_screen_info): Take a needs_reprobe
	argument.  We'll use XRRGetScreenResourcesCurrent() or
	XRRGetScreenResources() as appropriate.
	(screen_on_event): Don't re-probe RANDR for all events; just for
	RRScreenChangeNotify.  This avoids expensive probing for (e.g.)
	when only output properties change (RRNotify).