3
votes

tl;dr:

Usually, the horizontal constraint equations and the vertical constraint equations are independent of each other but an aspect ratio constraint links both dimensions, merging the two smaller sets of linear equations into one big set. From my understanding the two smaller sets should be easier to solve than the combined big set and thus, I expected aspect ratio constraints to reduce performance. However, a simple test with 100 constrained views in each dimension showed no difference in performance. Why?


The Question in Detail:

Constraints are linear equations

In Auto Layout, each layout constraint is a linear equation:

view2.attribute = multiplier * view1.attribute + constant

A non-ambiguous and non-conflicting layout is given, when the set of all constraints has exactly one solution.

Inside the method layoutSubviews() the system resolves the constraints i.e. it computes the frames for all subviews from these constraints. The task is to solve a system of linear equations which could be done by applying the Gauss algorithm.

x and y: Two independent sets of equations

Now as long as there are no aspect ratio constraints involved the horizontal and the vertical dimension are independent of each other. Thus, there is one set of h linear equations for the horizontal constraints and one set of v linear equations for the vertical constraints. These can be solved separately.

However, adding an aspect ratio constraint to the view links both dimensions. Instead of two independent sets of linear equations the system has to solve one bigger set of h + v linear equations.

The complexity of solving sets of linear equations

As the complexity of solving a system of n linear equations is 
somewhere between O(n2) and O(n3), depending on the algorithm, it must be faster to solve two systems with h and v equations than one system with h + v equations. Hence I would expect that the process of resolving constraints (i.e. the layoutSubviews() method) takes notably longer as soon as there is at least one aspect ratio constraint present.

To figure this out I created an empty sample project, added 100 views along the horizontal and 100 views along the vertical axis and constrained them properly. Then I measured the time of the layout process:

override func layoutSubviews() {
    let t1 = mach_absolute_time()
    super.layoutSubviews()
    let t2 = mach_absolute_time()

    print(t2 - t1)
}

Then I replaced one of the vertical constraints with an aspect ratio constraint and measured the time again. The result was pretty much the same. This is the part that I don't understand.

Why does an aspect ratio constraint not have a bad impact on layout performance?

Here's the setup of the views that I created and constrained. For better visibility the screenshots only show 20 views in each direction instead of the 100 views for which I measured the time.

Screenshot of the views without aspect ratio constraint Screenshot of the views with aspect ratio constraint

2
Can you share details about the aspect ratio constraint that you used? - juanjo
Of course: I simply added a view.width = view.height constraint to the view in the upper left corner. All the views in the top row have equalHeight constraints, all the views in the left column have equalWidth constraints. - Mischa
Are you sure those are the only constraints that you added? Is there any other leading or trailing constraints or horizontal constraints between the views? because with the constraints described, I think it's not possible to calculate every frame - juanjo
I didn't say I mentioned all the constraints involved. You only asked for the aspect ratio constraint. :) Of course, there are also constraints for keeping the views in place, e.g. trailing to leading constraints between all the horizontal views and bottom to top constraints between all the vertical views. - Mischa
Sorry you're right - juanjo

2 Answers

1
votes

I don't know the implementation details but your logic argument seems fair.

The simple test you describe is just too basic to be able to tell the difference, the computer / processor is so fast at making the calculations that for a small sample size like 100 views the completion time, or rather the variance between completion times is minimal.

Your test should really use thousands or hundreds of thousands of views.

Also, computers / processors do lots of different things all the time, they're parallel processing. Sometimes this is over multiple cores, but each core also does multiple different things 'at the same time. This impacts your results as you don't know what was happening while you were timing.

Your test should really be run thousands or hundreds of thousands of times.

So, if you increase the 'complexity' of the testing, and the number of equations to be solved then you should begin to see the differences in the relative cost to solve those equations.

1
votes

Adding an aspect ratio constraint doesn't necessarily make the set of equations dependent on each other, with the constraints you described the equation for x position and width of all the views in the top row can be calculated without the necessity to solve first the vertical equations or joining the equations, once the engine solves the first set of equations it only needs to solve the y equations with a constant instead of a system of equations, and the same applies for the vertical column of views.

The engine that solves this equations (I guess) have heuristics that can improve performance based on the previous conclusions, and a lot more I think.

I think that you could force a situation which can only be solved by solving the system of equations, but I'm afraid that Interface Builder is going to show constraint errors, but I cannot think of such a situation now.