Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS autolayout performance issue in portrait mode. [NSISEngine optimize]

Tags:

ios

autolayout

I have encountered a very strange problem and I was wondering, if anyone could help me out here since I'm totally lost.

Context: I am developing an app with a relatively simple hierarchy. Just a few view controller but quite a lot of high-res images. They are presented in a UIScrollView with some text etc. While testing it in portrait mode the scrollview didn't scroll smoothly at all. It seemed like the framerate droped to about 4-5 fps. First I thought it was because of the high-res images.

But then I turned the iPad to landscape mode and everything ran smoothly. Since the I have a separate xib-file for portrait and landscape, I thought there has to be a problem in the portrait-xib. It turned out, there wasn't. Both had the same VC-class and where therefore using the same code and both xibs are almost identical except for the sizes and positions of the views.

To narrow the problem down, I used Instrument's TimeProfiler to see whats causing the problem. As it turned out, TimeProfiler showed some calls to [NSISEngine optimize] (triggered by NSLayoutConstraint). In portrait mode were more calls and those calls took much longer. Further down the tree I saw that in portrait mode [NSISEngine optimize] called [NSISEngine fixupIntegralizationViolations] and in landscape it didn't.

I even removed all the viewcontroller's from the app except for the rootVC and one other which is presented by the rootVC. The presented vc just contains some images, buttons and some animations. It has only one xib for both orientations and is (as all others too) layed out with autolayout.

The layout works as it should in both orientations and there are no ambiguities (as far as i can tell. at least po [[UIWindow keyWindow] _autolayoutTrace] doesn't show any).

I've attached a screenshot of the TimeProfile of the presentation process of the vc. One for portrait and one for landscape. As you can see, in landscape the calls to [NSISEngine optimize] take only a millisecond while in portrait they take over 3000ms.

Is there anyone who can tell me why that is? Or maybe has any idea what I can do to find out what the problem is?

Any help would be greatly appreciated!

Thx

Link to a larger version of the image: link

Instruments Timeprofiler screenshot

like image 977
Tobi Avatar asked Oct 18 '12 01:10

Tobi


2 Answers

I ran into the same issue with a moderately complex view where it performed well on non-Retina iPads or a Retina iPad in portrait mode. In landscape mode on a Retina device it took 10x longer to display a popover or push another view on the view stack. I ended up replacing the XIB file with a hand coded loadView in the view controller. That appears to have eliminated the problem. Interface builder has a tendency to create excessive constraints, so getting that under control is key to good auto layout performance.

I have also opened a support ticket on this problem.

Update:

I found the cause in my situation. It was the following set of constraints:

NSArray *constraints = [NSLayoutConstraint
                        constraintsWithVisualFormat : @"|[sunLabel][monLabel(==sunLabel)][tueLabel(==sunLabel)][wedLabel(==sunLabel)][thuLabel(==sunLabel)][friLabel(==sunLabel)][satLabel(==sunLabel)]|"
                        options : 0
                        metrics : nil
                        views : labelViewsDictionary];

It specifies that 7 labels within a parent view all share the same size and all extend the width of the parent view. I believe that the excessive relational nature of the layout was giving auto layout fits, particularly because the parent view width was not evenly divisible by 7.

To resolve it, I created an array of constraints that specify the width of each label and applied those constraints. When the device rotates the width of the parent changes so I go back and adjust the constant on the constraints to be 1/7th of the parent view width. This now performs well, the process of loading a popover now takes less than 300ms rather than 2000ms.

like image 75
Jack Cox Avatar answered Nov 14 '22 21:11

Jack Cox


I filed a tech support request regarding this issue and finally got the answer, that it's most likely a bug. Bug report is filed. Hopefully they'll fix it soon. If there's any news I'll update this answer.

like image 42
Tobi Avatar answered Nov 14 '22 22:11

Tobi