RectangleList::consolidate()


#1

Every once in a while, my Mac application goes into “beach ball mode” for a few seconds. I’ve determined that it’s getting bogged down in RectangleList::consolidate(). Any idea what’s going on here? Lots and lots and lots of regions being handled in here… I don’t see any slow-down like this on the Win side of things.

Incidentally, this routine used to hang my Mac app for minutes in previous versions of JUCE, but Jules’ recent changes improved performance greatly. I didn’t notice any problems until my last build. Could I have too many repaints() or something along those lines?

Thanks.


#2

Yes, I optimised that stuff quite heavily as I could a couple of versions back, but it could still occasionally get slow if you’ve sent it a lot (and it’d have to be really quite a lot) of small repaint regions that form a complex pattern.

The algorithm for consolidating will get progressively slower the more separate rectangles it has to keep track of… if I think of a better algorithm, I’ll change it!


#3

In this case, it hangs for about five seconds when getNumRectangles() is as small as 146. I modified the code like this to improve performance in my app:

[code]void RectangleList::consolidate()
{

// avoid large numbers of rectangles hanging the Mac
if (getNumRectangles() > 100)
{
	const Rectangle r(getBounds());
	clear();
	add(r);
}

…[/code]

I’m not suggesting this be a JUCE change; it just works for my app’s graphical needs and I thought I’d put it out there in case anyone else experiences something similar and wants to try it. I’m tempted to drop the threshold to 50, but I really don’t know how well consolidate() optimises redrawing on the Mac and I don’t want to mess with it too much.


#4

How about tweaking juce_mac_Windowing.cpp instead - try this:

        for (int i = regions.size(); --i >= 0;)
        {
            if (regions.getUnchecked(i)->window == window)
            {
                RectangleList& rects = regions.getUnchecked(i)->region;

                rects.add (x, y, w, h);

                if (rects.getNumRectangles() > 100)
                {
                    const Rectangle r (rects.getBounds());
                    rects.clear();
                    rects.add (r);
                }
                else if (rects.getNumRectangles() > 50)
                {
                    rects.consolidate();

                    if (rects.getNumRectangles() > 50)
                    {
                        const Rectangle r (rects.getBounds());
                        rects.clear();
                        rects.add (r);
                    }
                }

                return;
            }
        }

…if that works better for your setup, let me know and I’ll add it to the build.


#5

That’s where I got the idea and had it originally. It works well, but I wanted to make sure it was always called for consolidate(), not just in that one routine, which is why I put it into consolidate() itself. That’s really the only trouble spot, though, so that should be fine. Thanks.


#6