Merge lp:~smspillaz/compiz-core/compiz-core.optimization-inlining into lp:compiz-core

Proposed by Sam Spilsbury
Status: Superseded
Proposed branch: lp:~smspillaz/compiz-core/compiz-core.optimization-inlining
Merge into: lp:compiz-core
Diff against target: 338 lines (+129/-78)
9 files modified
include/core/region.h (+1/-1)
include/core/window.h (+11/-7)
src/privatewindow.h (+16/-0)
src/rect/include/core/rect.h (+19/-0)
src/region.cpp (+0/-6)
src/window.cpp (+9/-0)
src/window/geometry/include/core/windowgeometry.h (+1/-1)
src/window/geometry/src/windowgeometry.cpp (+0/-6)
src/windowgeometry.cpp (+72/-57)
To merge this branch: bzr merge lp:~smspillaz/compiz-core/compiz-core.optimization-inlining
Reviewer Review Type Date Requested Status
Daniel van Vugt Needs Fixing
Alan Griffiths Approve
Review via email: mp+95094@code.launchpad.net

This proposal has been superseded by a proposal from 2012-04-19.

Description of the change

Optimize and inline some hot-spots in CompWindow.

server*Rect and *Rect were being called quite a lot and unnecessarily being recalculated and copy-constructed (eg XCreateRegion madness). This branch inlines some functions that were being called a ton (compiz::window::Geometry::border () about 600,000 times) and adds a new RecalcRect class. RecalcRect takes a function object to recalculate a CompRect. At the moment, we use the old behaviour of recalculating server*Rect and *Rect every time they are called but once https://code.launchpad.net/~smspillaz/compiz-core/compiz-core.work_923683 is merged then we can optimize there.

To post a comment you must log in.
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

Not really relevant to the change, but as "Region handle () const" compiles there's already a declaration of Region visible - so why is priv a "void*" and cast all the while?

review: Approve
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

priv is a void* because in the penultimate revision before that change was merged, priv could represent different types (Region or PrivateRegion). Now that PrivateRegion is gone however you are correct that priv could be simply "Region priv".

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

I haven't tested it yet, but I'm pretty sure this branch should contain a CORE_ABIVERSION bump.

review: Needs Fixing
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

> I haven't tested it yet, but I'm pretty sure this branch should contain a
> CORE_ABIVERSION bump.

Good catch

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

8 - Region handle () const;
9 + Region handle () const { return static_cast<Region> (priv); }

I noticed also that CompRegion::handle is the most commonly called function in compiz. However it is also tiny and only accounts for 1% of compiz CPU usage. Which is why I didn't touch it.

Another problem with changing handle() is that if we change the implementation of CompRegion in future then we will need to change handle() again and that would be another ABI bump.

I think a better solution to solve all of these problems is to keep handle() unchanged, and add a new method:
    private:
        Region privHandle () const { return static_cast<Region> (priv); }
for use in region.cpp only.

review: Needs Fixing
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Or simply:
    #define REGIONHANDLE (static_cast<Region> (priv))
in region.cpp

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Also, testing this code I notice another windows-shifted-horizontally regression (though I suspect it's the same one and we haven't fixed the root cause yet). When a window is maximized or restored, it's contents are shifted to the right/left of where they should be. When you move the window, the shift corrects itself.

:(

review: Needs Fixing
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Though it's possible the shift regression would be fixed by merging the other branch Sam mentions...

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Confirmed: The shift regression seen with this branch is fixed if you also merge:
lp:~smspillaz/compiz-core/compiz-core.work_923683
But that branch has its own problems.

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

> 8 - Region handle () const;
> 9 + Region handle () const { return static_cast<Region> (priv); }
>
> I noticed also that CompRegion::handle is the most commonly called function in
> compiz. However it is also tiny and only accounts for 1% of compiz CPU usage.
> Which is why I didn't touch it.
>
> Another problem with changing handle() is that if we change the implementation
> of CompRegion in future then we will need to change handle() again and that
> would be another ABI bump.

We change the ABI for other reasons too, and I really don't think the implementation of CompRegion is going to change (except, perhaps to cairo_region_t), so this is just a total non-issue.

>
> I think a better solution to solve all of these problems is to keep handle()
> unchanged, and add a new method:
> private:
> Region privHandle () const { return static_cast<Region> (priv); }
> for use in region.cpp only.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

CompRegion::handle()
I think this may be worth inlining privately. As mentioned earlier. We shouldn't make handle() inline for external users of the class. FYI, CompRegion::handle() is consistently the single most called function in compiz, however it never accounts for more than 1.3% of the total CPU usage.

compiz::window::Geometry::border ()
Makes no sense to inline AFAICS. It may well be around the 25th most called function, however it only accounts for 0.07% of the CPU usage.

CompWindow::borderRect()
Does not need to optimizing at all. Is almost never called and contributes absolutely nothing to the total CPU usage.

*Rect()
Contribute almost nothing measurable to the CPU usage.

All-in-all, these optimizations don't seem to provide any significant benefit. I think CompRegion::handle() could be optimized using a private inline version of that function. But even then, the maximum gain is going to be about 1%. The rest of the changes break the ABI, cause a regression, and do not appear to be required at all.

If I'm wrong, then please log a bug with the profile data showing why all this existing code needs optimizing.

review: Disapprove
Revision history for this message
Sam Spilsbury (smspillaz) wrote :

On Mon, 5 Mar 2012, Daniel van Vugt wrote:

> Review: Disapprove
>
> CompRegion::handle()
> I think this may be worth inlining privately. As mentioned earlier. We shouldn't make handle() inline for external users of the class. FYI, CompRegion::handle() is consistently the single most called function in compiz, however it never accounts for more than 1.3% of the total CPU usage.
>

Ack, although other plugins use the handle directly.

> compiz::window::Geometry::border ()
> Makes no sense to inline AFAICS. It may well be around the 25th most called function, however it only accounts for 0.07% of the CPU usage.
>

Why not ? Avoids the JMP

> CompWindow::borderRect()
> Does not need to optimizing at all. Is almost never called and contributes absolutely nothing to the total CPU usage.
>

> *Rect()
> Contribute almost nothing measurable to the CPU usage.
>

They account for about 5% ish of usage, and are called during paint
functions. There is no reason for them to operate in the way that they
currently do. The constructors also involve XCreateRegion and
XDestroyRegion pairs.

Just because the optimization isn't "significant" that doesn't mean that
it is useless. In fact, the code as it was written makes no sense
whatsoever, and there isn't any reason to keep it as it is.

> All-in-all, these optimizations don't seem to provide any significant benefit. I think CompRegion::handle() could be optimized using a private inline version of that function. But even then, the maximum gain is going to be about 1%. The rest of the changes break the ABI, cause a regression, and do not appear to be required at all.
>

The regression is unrelated, see
lp:~smspillaz/compiz-core/compiz-core.backport_2988_work_923683

> If I'm wrong, then please log a bug with the profile data showing why all this existing code needs optimizing.
> --
> https://code.launchpad.net/~smspillaz/compiz-core/compiz-core.optimization-inlining/+merge/95094
> You are the owner of lp:~smspillaz/compiz-core/compiz-core.optimization-inlining.
>

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Still causes the shift regression, despite us thinking it was fixed by:
https://code.launchpad.net/+branch/~smspillaz/compiz-core/compiz-core.backport_2988_work_923683
It seems that fix has not worked.

Aside from the shift regression which still needs fixing, I strongly recommend not breaking the ABI (now and again in future) by inlining handle() or border(). If anything, I suggest adding new inline functions "inlineHandle" and "inlineBorder". Ideally they should be private. If not private, then they should be documented as "only safe to use in core or core plugins".

CORE_ABIVERSION still needs bumping too.

review: Needs Fixing
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

And yes, when I say "causes the shift regression" I actually mean "triggers the shift regression". I'm pretty sure the bug is not in the below diff, only exploited by it.

Unmerged revisions

3027. By Sam Spilsbury

Added RecalcRect, a class which has a function to recalculate a rectangle on demand,
currently replaces *Rect () in window and allows them to be const &, soon we will be
able to only recalculate these when necessary and not all the time

3026. By Sam Spilsbury

Inline some heavily called CompRegion and compiz::window::Geometry types

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'include/core/region.h'
--- include/core/region.h 2012-02-27 03:41:13 +0000
+++ include/core/region.h 2012-02-29 03:40:25 +0000
@@ -71,7 +71,7 @@
71 /**71 /**
72 * Returns the internal XRegion handle72 * Returns the internal XRegion handle
73 */73 */
74 Region handle () const;74 Region handle () const { return static_cast<Region> (priv); }
7575
76 /**76 /**
77 * Returns true if the specified CompPoint falls within the77 * Returns true if the specified CompPoint falls within the
7878
=== modified file 'include/core/window.h'
--- include/core/window.h 2012-02-16 09:55:06 +0000
+++ include/core/window.h 2012-02-29 03:40:25 +0000
@@ -317,19 +317,23 @@
317 /* With border */317 /* With border */
318 int serverWidth () const;318 int serverWidth () const;
319 int serverHeight () const;319 int serverHeight () const;
320 const CompSize serverSize () const;320 CompSize serverSize () const;
321321
322 /* effective decoration extents */322 /* effective decoration extents */
323 CompRect borderRect () const;323 const CompRect & borderRect () const;
324 CompRect serverBorderRect () const;324 const CompRect & serverBorderRect () const;
325325
326 /* frame window geometry */326 /* frame window geometry */
327 CompRect inputRect () const;327 const CompRect & inputRect () const;
328 CompRect serverInputRect () const;328 const CompRect & serverInputRect () const;
329329
330 /* includes decorations and shadows */330 /* includes decorations and shadows */
331 CompRect outputRect () const;331 const CompRect & outputRect () const;
332 CompRect serverOutputRect () const;332 const CompRect & serverOutputRect () const;
333
334 /* only includes X11 borders */
335 const CompRect & geometryBorders () const;
336 const CompRect & serverGeometryBorders () const;
333337
334 Window id ();338 Window id ();
335 Window frame ();339 Window frame ();
336340
=== modified file 'src/privatewindow.h'
--- src/privatewindow.h 2012-02-14 14:37:04 +0000
+++ src/privatewindow.h 2012-02-29 03:40:25 +0000
@@ -209,6 +209,13 @@
209209
210 bool checkClear ();210 bool checkClear ();
211211
212 void recalcExtentsRect (CompRect &rect,
213 const CompWindow::Geometry *geometry,
214 const CompWindowExtents *extents);
215
216 void recalcGeometryBordersRect (CompRect &rect,
217 const CompWindow::Geometry *geometry);
218
212 public:219 public:
213220
214 PrivateWindow *priv;221 PrivateWindow *priv;
@@ -251,6 +258,15 @@
251 CompRegion inputRegion;258 CompRegion inputRegion;
252 CompRegion frameRegion;259 CompRegion frameRegion;
253260
261 compiz::rect::RecalcRect borderRect;
262 compiz::rect::RecalcRect serverBorderRect;
263 compiz::rect::RecalcRect inputRect;
264 compiz::rect::RecalcRect serverInputRect;
265 compiz::rect::RecalcRect outputRect;
266 compiz::rect::RecalcRect serverOutputRect;
267 compiz::rect::RecalcRect geometryBorders;
268 compiz::rect::RecalcRect serverGeometryBorders;
269
254 unsigned int wmType;270 unsigned int wmType;
255 unsigned int type;271 unsigned int type;
256 unsigned int state;272 unsigned int state;
257273
=== modified file 'src/rect/include/core/rect.h'
--- src/rect/include/core/rect.h 2012-01-19 19:32:29 +0000
+++ src/rect/include/core/rect.h 2012-02-29 03:40:25 +0000
@@ -33,6 +33,8 @@
33#include <X11/Xlib.h>33#include <X11/Xlib.h>
34#include <X11/Xutil.h>34#include <X11/Xutil.h>
35#include <X11/Xregion.h>35#include <X11/Xregion.h>
36#include <boost/function.hpp>
37#include <boost/bind.hpp>
36#include "core/point.h"38#include "core/point.h"
3739
3840
@@ -144,6 +146,23 @@
144 {146 {
145 CompPoint wraparoundPoint (const CompRect &bounds,147 CompPoint wraparoundPoint (const CompRect &bounds,
146 const CompPoint &p);148 const CompPoint &p);
149
150 class RecalcRect
151 {
152 public:
153
154 typedef boost::function <void (CompRect &rect)> RecalcFunc;
155
156 RecalcRect (const RecalcFunc &func);
157
158 const CompRect & rect () const { return mRect; }
159 void refresh () { mRecalcFunc (mRect); }
160
161 private:
162
163 CompRect mRect;
164 RecalcFunc mRecalcFunc;
165 };
147 }166 }
148}167}
149168
150169
=== modified file 'src/region.cpp'
--- src/region.cpp 2012-02-27 08:05:51 +0000
+++ src/region.cpp 2012-02-29 03:40:25 +0000
@@ -118,12 +118,6 @@
118 priv = XCreateRegion ();118 priv = XCreateRegion ();
119}119}
120120
121Region
122CompRegion::handle () const
123{
124 return static_cast<Region> (priv);
125}
126
127CompRegion &121CompRegion &
128CompRegion::operator= (const CompRegion &c)122CompRegion::operator= (const CompRegion &c)
129{123{
130124
=== modified file 'src/window.cpp'
--- src/window.cpp 2012-02-20 02:30:34 +0000
+++ src/window.cpp 2012-02-29 03:40:25 +0000
@@ -6589,6 +6589,15 @@
6589 width (0),6589 width (0),
6590 height (0),6590 height (0),
6591 region (),6591 region (),
6592 frameRegion (),
6593 borderRect (boost::bind (&PrivateWindow::recalcExtentsRect, this, _1, &geometry, &border)),
6594 serverBorderRect (boost::bind (&PrivateWindow::recalcExtentsRect, this, _1, &serverGeometry, &border)),
6595 inputRect (boost::bind (&PrivateWindow::recalcExtentsRect, this, _1, &geometry, &input)),
6596 serverInputRect (boost::bind (&PrivateWindow::recalcExtentsRect, this, _1, &serverGeometry, &serverInput)),
6597 outputRect (boost::bind (&PrivateWindow::recalcExtentsRect, this, _1, &geometry, &output)),
6598 serverOutputRect (boost::bind (&PrivateWindow::recalcExtentsRect, this, _1, &serverGeometry, &output)),
6599 geometryBorders (boost::bind (&PrivateWindow::recalcGeometryBordersRect, this, _1, &geometry)),
6600 serverGeometryBorders (boost::bind (&PrivateWindow::recalcGeometryBordersRect, this, _1, &serverGeometry)),
6592 wmType (0),6601 wmType (0),
6593 type (CompWindowTypeUnknownMask),6602 type (CompWindowTypeUnknownMask),
6594 state (0),6603 state (0),
65956604
=== modified file 'src/window/geometry/include/core/windowgeometry.h'
--- src/window/geometry/include/core/windowgeometry.h 2012-01-19 20:08:32 +0000
+++ src/window/geometry/include/core/windowgeometry.h 2012-02-29 03:40:25 +0000
@@ -55,7 +55,7 @@
55 Geometry ();55 Geometry ();
56 Geometry (int x, int y, int width, int height, int border);56 Geometry (int x, int y, int width, int height, int border);
5757
58 int border () const;58 int border () const { return mBorder; }
5959
60 void set (int x, int y, int width, int height, int border);60 void set (int x, int y, int width, int height, int border);
61 void setBorder (int border);61 void setBorder (int border);
6262
=== modified file 'src/window/geometry/src/windowgeometry.cpp'
--- src/window/geometry/src/windowgeometry.cpp 2012-01-19 20:08:32 +0000
+++ src/window/geometry/src/windowgeometry.cpp 2012-02-29 03:40:25 +0000
@@ -41,12 +41,6 @@
41{41{
42}42}
4343
44int
45compiz::window::Geometry::border () const
46{
47 return mBorder;
48}
49
50void44void
51compiz::window::Geometry::setBorder (int border)45compiz::window::Geometry::setBorder (int border)
52{46{
5347
=== modified file 'src/windowgeometry.cpp'
--- src/windowgeometry.cpp 2012-01-23 05:44:19 +0000
+++ src/windowgeometry.cpp 2012-02-29 03:40:25 +0000
@@ -113,7 +113,7 @@
113 2 * priv->serverGeometry.border ();113 2 * priv->serverGeometry.border ();
114}114}
115115
116const CompSize116CompSize
117CompWindow::serverSize () const117CompWindow::serverSize () const
118{118{
119 return CompSize (priv->serverGeometry.width () +119 return CompSize (priv->serverGeometry.width () +
@@ -122,68 +122,83 @@
122 2 * priv->serverGeometry.border ());122 2 * priv->serverGeometry.border ());
123}123}
124124
125CompRect125void
126PrivateWindow::recalcExtentsRect (CompRect &rect, const CompWindow::Geometry *geometry, const CompWindowExtents *extents)
127{
128 rect.setGeometry (geometry->x () - geometry->border () - extents->left,
129 geometry->y () - geometry->border () - extents->top,
130 geometry->width () + geometry->border () * 2 +
131 extents->left + extents->right,
132 geometry->height () + geometry->border () * 2 +
133 extents->top + extents->bottom);
134}
135
136void
137PrivateWindow::recalcGeometryBordersRect (CompRect &rect, const CompWindow::Geometry *geometry)
138{
139 rect.setGeometry (geometry->x () - geometry->border (),
140 geometry->y () - geometry->border (),
141 geometry->width () + geometry->border () * 2,
142 geometry->height () + geometry->border () * 2);
143}
144
145compiz::rect::RecalcRect::RecalcRect (const RecalcFunc &func) :
146 mRecalcFunc (func)
147{
148}
149
150const CompRect &
126CompWindow::borderRect () const151CompWindow::borderRect () const
127{152{
128 return CompRect (priv->geometry.x () - priv->geometry.border () - priv->border.left,153 priv->borderRect.refresh ();
129 priv->geometry.y () - priv->geometry.border () - priv->border.top,154 return priv->borderRect.rect ();
130 priv->geometry.width () + priv->geometry.border () * 2 +155}
131 priv->border.left + priv->border.right,156
132 priv->geometry.height () + priv->geometry.border () * 2 +157const CompRect &
133 priv->border.top + priv->border.bottom);158CompWindow::inputRect () const
134}159{
135160 priv->inputRect.refresh ();
136CompRect161 return priv->inputRect.rect ();
162}
163
164const CompRect &
165CompWindow::outputRect () const
166{
167 priv->outputRect.refresh ();
168 return priv->outputRect.rect ();
169}
170
171const CompRect &
137CompWindow::serverBorderRect () const172CompWindow::serverBorderRect () const
138{173{
139 return CompRect (priv->serverGeometry.x () - priv->geometry.border () - priv->border.left,174 priv->serverBorderRect.refresh ();
140 priv->serverGeometry.y () - priv->geometry.border () - priv->border.top,175 return priv->serverBorderRect.rect ();
141 priv->serverGeometry.width () + priv->geometry.border () * 2 +176}
142 priv->border.left + priv->border.right,177
143 priv->serverGeometry.height () + priv->geometry.border () * 2 +178const CompRect &
144 priv->border.top + priv->border.bottom);
145}
146
147CompRect
148CompWindow::inputRect () const
149{
150 return CompRect (priv->geometry.x () - priv->geometry.border () - priv->serverInput.left,
151 priv->geometry.y () - priv->geometry.border () - priv->serverInput.top,
152 priv->geometry.width () + priv->geometry.border () * 2 +
153 priv->serverInput.left + priv->serverInput.right,
154 priv->geometry.height () +priv->geometry.border () * 2 +
155 priv->serverInput.top + priv->serverInput.bottom);
156}
157
158CompRect
159CompWindow::serverInputRect () const179CompWindow::serverInputRect () const
160{180{
161 return CompRect (priv->serverGeometry.x () - priv->serverGeometry.border () - priv->serverInput.left,181 priv->serverInputRect.refresh ();
162 priv->serverGeometry.y () - priv->serverGeometry.border () - priv->serverInput.top,182 return priv->serverInputRect.rect ();
163 priv->serverGeometry.width () + priv->serverGeometry.border () * 2 +183}
164 priv->serverInput.left + priv->serverInput.right,184
165 priv->serverGeometry.height () + priv->serverGeometry.border () * 2 +185const CompRect &
166 priv->serverInput.top + priv->serverInput.bottom);
167}
168
169CompRect
170CompWindow::outputRect () const
171{
172 return CompRect (priv->geometry.x () - priv->serverGeometry.border ()- priv->output.left,
173 priv->geometry.y () - priv->serverGeometry.border () - priv->output.top,
174 priv->geometry.width () + priv->serverGeometry.border () * 2 +
175 priv->output.left + priv->output.right,
176 priv->geometry.height () + priv->serverGeometry.border () * 2 +
177 priv->output.top + priv->output.bottom);
178}
179
180CompRect
181CompWindow::serverOutputRect () const186CompWindow::serverOutputRect () const
182{187{
183 return CompRect (priv->serverGeometry.x () - priv->serverGeometry.border () - priv->output.left,188 priv->serverOutputRect.refresh ();
184 priv->serverGeometry.y () - priv->serverGeometry.border () - priv->output.top,189 return priv->serverOutputRect.rect ();
185 priv->serverGeometry.width () + priv->serverGeometry.border () * 2 +190}
186 priv->output.left + priv->output.right,191
187 priv->serverGeometry.height () + priv->serverGeometry.border () * 2 +192const CompRect &
188 priv->output.top + priv->output.bottom);193CompWindow::geometryBorders () const
194{
195 priv->geometryBorders.refresh ();
196 return priv->geometryBorders.rect ();
197}
198
199const CompRect &
200CompWindow::serverGeometryBorders () const
201{
202 priv->serverGeometryBorders.refresh ();
203 return priv->serverGeometryBorders.rect ();
189}204}

Subscribers

People subscribed via source and target branches