Re: Responsive scrolling control with lots of subviews
Re: Responsive scrolling control with lots of subviews
- Subject: Re: Responsive scrolling control with lots of subviews
- From: Uli Kusterer <email@hidden>
- Date: Mon, 02 Mar 2015 16:45:34 +0100
On 02 Mar 2015, at 15:54, Ben <email@hidden> wrote:
>> On 2 Mar 2015, at 14:10, Mike Abdullah <email@hidden> wrote:
>>> On 2 Mar 2015, at 11:44, Ben <email@hidden> wrote:
>>>
>>> Hi list,
>>>
>>> Since NSCell is apparently on the way out, I've been trying to build a new control I need using views. It's a cut-down spreadsheet-alike grid, similar to MBTableGrid here: https://github.com/brendand/mbtablegrid
>>>
>>> Unfortunately, I am running into the to-be-expected performance trouble with keeping a couple of hundred subviews in my control at the same time. It particularly hurts when scrolling. Stuff I've tried includes:
>>>
>>> - Removing the off-screen views when possible (still leaves about 150 on screen)
>>> - Keeping a queue of reusable views to avoid allocating new ones
>>> - Attempting to have one view per grid item type and treat it like an NSCell (i.e., lockFocus into the parent view and draw there)
>>>
>>> Clearly a smooth-scrolling view-based grid is possible - after all, NSTableView can do it. It's a shame I can't use it for this.
>>>
>>> Does anyone have any suggestions on how to achieve decent drawing/scrolling performance here?
>>
>> Can you offer any more explanation as to *what* is slow in your experiments? What is about the number of views that seems to be bogging your control down?
>
> Certainly:
>
> From a time profile, the majority of my code being called is funnelled through a single method which handles the adding/positioning/removing of views within the visible area. The slow areas are:
>
> 8% - Instantiating new views (happens early on, views are cached for reuse)
> 20% - Positioning new/reused views (a single -setFrame: call once for each view)
> 25% - Adding newly-visible subviews (-addSubview:)
> 17% - Enumerating off-screen columns for view removal (-removeFromSuperviewWithoutNeedingDisplay)
> 25% - Enumerating off-screen rows for view removal (-removeFromSuperviewWithoutNeedingDisplay)
> Remainder is misc small stuff. This method as a whole takes 19% of running time.
Are you re-setting *all* the views or only hiding views that scroll out and moving unused views to newly exposed areas? We've been doing stuff like that in various spots and performance is fine. One thing that might help is to make each table-row layer-backed, then you get zero-cost moving as it simply gets drawn in another location on the graphics card. My checklist for a view-based table view would be:
- Create (height/ row height) +1 row views and keep them around
- Make all rows layer-backed
- When scrolling, make sure you only modify the position, not the height, and do not call setNeedsDisplay: on any views whose contents haven't actually changed
- when a view goes out of view, re-use it for the newly-exposed area, and only then request a redraw, or otherwise hide it.
- Mark as many views as you can as opaque.
- Try to update items relatively to each other. I.e. just assume the bottom-most view is already positioned right and place the newly-exposed row's view under it, don't loop over all rows over and over again.
That said, we used to do the same without layer-backing in the Carbon and Classic days and Macs had sufficient performance, so that this is taking too long for you seems weird. Are these custom views? Are you rounding coordinates to integers to ensure they don't subtly change size due to rounding errors?
Also, I remember using PXListView (https://github.com/Perspx/PXListView <https://github.com/Perspx/PXListView>) a few years ago and contributing a bunch of performance fixes. It's not the code we're using these days (and it has changed a bit since then), but it might do one or the other optimization you're not doing, so may be a good point of reference.
Cheers,
-- Uli
http://stacksmith <http://stacksmith/>.org
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden