Skip to content

Commit cab00be

Browse files
author
Luc Dion
committed
Update doc + pod version
1 parent e79adbd commit cab00be

13 files changed

+248
-3
lines changed

FlexLayout.podspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Pod::Spec.new do |s|
33
s.name = "FlexLayout"
4-
s.version = "0.0.13"
4+
s.version = "0.1.1"
55
s.summary = "FlexLayout"
66

77
s.homepage = "https://github.com/lucmirego/FlexLayout.git"

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -742,11 +742,11 @@ As you can see in the following chart, FlexLayout and PinLayout's performance ar
742742

743743
These results also means that **FlexLayout and PinLayout are faster than any layout frameworks that is built over auto layout**.
744744

745-
[See here more complete details, results and explanation of the benchmark](docs/Benchmark.md).
745+
[See here more complete details, results and explanation of the benchmark](docs/benchmark/Benchmark.md).
746746

747747
<p align="center"> Tested on a iPhone 6 iOS 10.3.2</p>
748748
<p align="center">
749-
<img src="docs/images/benchmark/benchmark-iPhone6.png" alt="FlexLayout Performance" width=600/>
749+
<img src="docs/benchmark/benchmark_iphone6.png" alt="FlexLayout Performance" width=600/>
750750
</p>
751751

752752

docs/benchmark/Benchmark.md

+245
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
<p align="center">
2+
<img src="../images/flexlayout-logo-2.png" alt="FlexLayout and PinLayout Performance" width=100/>
3+
</p>
4+
5+
6+
<h1 align="center" style="color: #376C9D; font-family: Arial Black, Gadget, sans-serif; font-size: 1.5em">FlexLayout Benchmark</h1>
7+
8+
* [Methodology](#methodology)
9+
* [Results](#results)
10+
* [Code source comparison](#code_source_comparison)
11+
12+
<br>
13+
14+
## Methodology <a name="methodology"></a>
15+
16+
##### LayoutKit Benchmark
17+
FlexLayout and [PinLayout](https://github.com/mirego/PinLayout) performance has been tested using a fork of [LayoutKit](https://github.com/mirego/LayoutKit). LayoutKit include an example app with a really nice and simple benchmark. It is used to compare LayoutKit with Auto layout, UIStackViews and manual layouting.
18+
19+
The benchmark has been modified to also include [FlexLayout](https://github.com/lucdion/FlexLayout) and [PinLayout](https://github.com/mirego/LayoutKit/blob/master/LayoutKitSampleApp/Benchmarks/FeedItemPinLayoutView.swift). Remark how FlexLayout and PinLayout code is concise, clean and doesn't contain any computation [compared to Manual Layouting source code](#source_code_compare).
20+
21+
22+
The benchmark include tests for the following layout systems:
23+
24+
* Auto layout
25+
* Auto layout using UIStackViews
26+
* LayoutKit
27+
* Manual layout (i.e. set UIView's frame directly)
28+
* [FlexLayout](https://github.com/lucdion/FlexLayout)
29+
* [PinLayout](https://github.com/mirego/PinLayout)
30+
31+
Anyone who would like to integrate any other layout frameworks to this GitHub repository is welcome.
32+
33+
##### Benchmark details
34+
The LayoutKit benchmark layout UICollectionView and UITableView cells in multiple pass, each pass contains more cells than the previous one. The **X axis** in following charts indicates the **number of cells** contained for each pass. The **Y axis** indicates the **number of seconds** to render all cells from one pass.
35+
36+
##### Benchmark cell layout
37+
Here are the benchmark rendering results to compare visual results:
38+
39+
* [Auto layout rendering result](benchmark_result_Autolayout.png)
40+
* FlexLayout rendering result
41+
* [PinLayout rendering result](benchmark_result_PinLayout.png)
42+
* [LayoutKit rendering result](benchmark_result_LayoutKit.png)
43+
44+
<br>
45+
46+
## Results <a name="results"></a>
47+
48+
As you can see in the following chart, FlexLayout and PinLayout's performance are faster or equal to manual layouting. FlexLayout is **between 26x and 36x faster than auto layout** and PinLayout **between 12x and 16x faster than auto layout**, and this for all types of iPhone (5/6/6S/7)
49+
50+
These results means that FlexLayout and PinLayout are faster than any layout frameworks that is built over auto layout (SnapKit, Stevia, PureLayout, ...).
51+
52+
<br>
53+
54+
### FlexLayout and PinLayout performance compared to Auto layout
55+
56+
This table shows FlexLayout and PinLayout performance compared to Auto layout when layouting UICollectionView's cells.
57+
58+
The table shows that FlexLayout took 23 miliseconds to render 100 UICollectionView's cells on a iPhone 6 compared to 53 miliseconds for PinLayout and 611 ms for Auto layout. Its 26 time faster for FlexLayout and 12 time faster for PinLayout.
59+
60+
| | Auto layout time (seconds) | FlexLayout time (seconds) | Flex performance compared to Auto layout | PinLayout time (seconds) | PinLayout performance compared to Auto layout |
61+
|:---------:|:---------:|:---------:|:-----------------------------------------------------------------------:|:---------------------------:|:-------------------------:|
62+
| iPhone 5 | 2.074 | 0.067 | 31x Faster | 0.126 | 16x Faster |
63+
| iPhone 6 | 0.611 | 0.023 | 26x Faster | 0.053 | 12x Faster |
64+
| iPhone 6S | 0.344 | NA | NA | 0.029 | 12x Faster |
65+
| iPhone 7 | 0.293 | 0.008 | 37x Faster | 0.021 | 14x Faster |
66+
67+
<br>
68+
69+
#### Benchmark charts
70+
71+
:pushpin: You can see the benchmark raw data in this [spreadsheet](benchmark.xlsx).
72+
73+
<p align="center">
74+
<a href=""><img src="benchmark_iphone5.png" alt="PinLayout Performance"/></a>
75+
76+
<p align="center">
77+
<a href=""><img src="benchmark_iphone6.png" alt="PinLayout Performance"/></a>
78+
79+
<p align="center">
80+
<a href=""><img src="benchmark_iphone7.png" alt="PinLayout Performance"/></a>
81+
82+
<br>
83+
84+
## Code source comparison <a name="code_source_comparison"></a>
85+
This section shows the benchmark layout code for each type of layout framework.
86+
87+
88+
### FlexLayout source code
89+
90+
[See FlexLayout source code on GitHub](https://github.com/mirego/LayoutKit/blob/master/LayoutKitSampleApp/Benchmarks/FeedItemFlexLayoutView.swift)
91+
92+
```swift
93+
flexbox.addChild(contentView).padding(8).define { (flexbox) in
94+
flexbox.createBox().direction(.row).justify(.spaceBetween).define { (flexbox) in
95+
flexbox.addChild(actionLabel)
96+
flexbox.addChild(optionsLabel)
97+
}
98+
99+
flexbox.createBox().direction(.row).alignItems(.center).define({ (flexbox) in
100+
flexbox.addChild(posterImageView).width(50).height(50).marginRight(8)
101+
102+
flexbox.createBox().grow(1).define({ (flexbox) in
103+
flexbox.addChild(posterNameLabel)
104+
flexbox.addChild(posterHeadlineLabel)
105+
flexbox.addChild(posterTimeLabel)
106+
})
107+
})
108+
109+
flexbox.addChild(posterCommentLabel)
110+
111+
flexbox.addChild(contentImageView).aspectRatio(350 / 200)
112+
flexbox.addChild(contentTitleLabel)
113+
flexbox.addChild(contentDomainLabel)
114+
115+
flexbox.createBox().direction(.row).justify(.spaceBetween).marginTop(4).define({ (flexbox) in
116+
flexbox.addChild(likeLabel)
117+
flexbox.addChild(commentLabel)
118+
flexbox.addChild(shareLabel)
119+
})
120+
121+
flexbox.createBox().direction(.row).marginTop(2).define({ (flexbox) in
122+
flexbox.addChild(actorImageView).width(50).height(50).marginRight(8)
123+
flexbox.addChild(actorCommentLabel).grow(1)
124+
})
125+
}
126+
```
127+
128+
129+
### PinLayout source code
130+
131+
[See PinLayout source code on GitHub](https://github.com/mirego/LayoutKit/blob/master/LayoutKitSampleApp/Benchmarks/FeedItemPinLayoutView.swift)
132+
133+
```swift
134+
override func layoutSubviews() {
135+
super.layoutSubviews()
136+
137+
let hMargin: CGFloat = 8
138+
let vMargin: CGFloat = 2
139+
140+
optionsLabel.pin.topRight().margin(hMargin)
141+
actionLabel.pin.topLeft().margin(hMargin)
142+
143+
posterImageView.pin.below(of: actionLabel, aligned: .left).marginTop(10)
144+
posterNameLabel.pin.right(of: posterImageView, aligned: .top).margin(-6, 6).right(hMargin).sizeToFit()
145+
posterHeadlineLabel.pin.below(of: posterNameLabel, aligned: .left).right(hMargin).marginTop(1).sizeToFit()
146+
posterTimeLabel.pin.below(of: posterHeadlineLabel, aligned: .left).right(hMargin).marginTop(1).sizeToFit()
147+
148+
posterCommentLabel.pin.below(of: posterTimeLabel).left(hMargin).right().right(hMargin)
149+
.marginTop(vMargin).sizeToFit()
150+
151+
contentImageView.pin.below(of: posterCommentLabel).hCenter().width(100%).sizeToFit()
152+
contentTitleLabel.pin.below(of: contentImageView).left().right().marginHorizontal(hMargin).sizeToFit()
153+
contentDomainLabel.pin.below(of: contentTitleLabel, aligned: .left).right().marginRight(hMargin)
154+
.sizeToFit()
155+
156+
likeLabel.pin.below(of: contentDomainLabel, aligned: .left).marginTop(vMargin)
157+
commentLabel.pin.top(to: likeLabel.edge.top).hCenter(50%)
158+
shareLabel.pin.top(to: likeLabel.edge.top).right().marginRight(hMargin)
159+
160+
actorImageView.pin.below(of: likeLabel, aligned: .left).marginTop(vMargin)
161+
actorCommentLabel.pin.right(of: actorImageView, aligned: .center).marginLeft(4)
162+
}
163+
```
164+
165+
<br>
166+
167+
### Manual layout source code
168+
169+
[See Manual layout source code on GitHub](https://github.com/mirego/LayoutKit/blob/master/LayoutKitSampleApp/Benchmarks/FeedItemManualView.swift)
170+
171+
172+
```swift
173+
override func layoutSubviews() {
174+
super.layoutSubviews()
175+
176+
optionsLabel.frame = CGRect(x: bounds.width-optionsLabel.frame.width, y: 0,
177+
width: optionsLabel.frame.width, height: optionsLabel.frame.height)
178+
actionLabel.frame = CGRect(x: 0, y: 0, width: bounds.width-optionsLabel.frame.width, height: 0)
179+
actionLabel.sizeToFit()
180+
181+
posterImageView.frame = CGRect(x: 0, y: actionLabel.frame.bottom,
182+
width: posterImageView.frame.width, height: 0)
183+
posterImageView.sizeToFit()
184+
185+
let contentInsets = UIEdgeInsets(top: 0, left: 1, bottom: 2, right: 3)
186+
let posterLabelWidth = bounds.width-posterImageView.frame.width - contentInsets.left -
187+
contentInsets.right
188+
posterNameLabel.frame = CGRect(x: posterImageView.frame.right + contentInsets.left,
189+
y: posterImageView.frame.origin.y + contentInsets.top,
190+
width: posterLabelWidth, height: 0)
191+
posterNameLabel.sizeToFit()
192+
193+
let spacing: CGFloat = 1
194+
posterHeadlineLabel.frame = CGRect(x: posterImageView.frame.right + contentInsets.left,
195+
y: posterNameLabel.frame.bottom + spacing,
196+
width: posterLabelWidth, height: 0)
197+
posterHeadlineLabel.sizeToFit()
198+
199+
posterTimeLabel.frame = CGRect(x: posterImageView.frame.right + contentInsets.left,
200+
y: posterHeadlineLabel.frame.bottom + spacing, width: posterLabelWidth,
201+
height: 0)
202+
posterTimeLabel.sizeToFit()
203+
204+
posterCommentLabel.frame = CGRect(x: 0, y: max(posterImageView.frame.bottom,
205+
posterTimeLabel.frame.bottom +
206+
contentInsets.bottom),
207+
width: frame.width, height: 0)
208+
posterCommentLabel.sizeToFit()
209+
210+
contentImageView.frame = CGRect(x: frame.width/2 - contentImageView.frame.width/2,
211+
y: posterCommentLabel.frame.bottom, width: frame.width, height: 0)
212+
contentImageView.sizeToFit()
213+
214+
contentTitleLabel.frame = CGRect(x: 0, y: contentImageView.frame.bottom, width: frame.width, height: 0)
215+
contentTitleLabel.sizeToFit()
216+
217+
contentDomainLabel.frame = CGRect(x: 0, y: contentTitleLabel.frame.bottom, width: frame.width, height: 0)
218+
contentDomainLabel.sizeToFit()
219+
220+
likeLabel.frame = CGRect(x: 0, y: contentDomainLabel.frame.bottom, width: 0, height: 0)
221+
likeLabel.sizeToFit()
222+
223+
commentLabel.sizeToFit()
224+
commentLabel.frame = CGRect(x: frame.width/2-commentLabel.frame.width/2,
225+
y: contentDomainLabel.frame.bottom,
226+
width: commentLabel.frame.width, height: commentLabel.frame.height)
227+
228+
shareLabel.sizeToFit()
229+
shareLabel.frame = CGRect(x: frame.width-shareLabel.frame.width, y: contentDomainLabel.frame.bottom,
230+
width: shareLabel.frame.width, height: shareLabel.frame.height)
231+
232+
actorImageView.frame = CGRect(x: 0, y: likeLabel.frame.bottom, width: 0, height: 0)
233+
actorImageView.sizeToFit()
234+
235+
actorCommentLabel.frame = CGRect(x: actorImageView.frame.right, y: likeLabel.frame.bottom,
236+
width: frame.width-actorImageView.frame.width, height: 0)
237+
actorCommentLabel.sizeToFit()
238+
}
239+
```
240+
241+
<br>
242+
243+
### Auto layout source code
244+
245+
[See Auto layout source code on GitHub](https://github.com/mirego/LayoutKit/blob/master/LayoutKitSampleApp/Benchmarks/FeedItemAutoLayoutView.swift)

docs/benchmark/benchmark.xlsx

50.9 KB
Binary file not shown.

docs/benchmark/benchmark_iphone5.png

113 KB
Loading

docs/benchmark/benchmark_iphone6.png

122 KB
Loading

docs/benchmark/benchmark_iphone6s.png

118 KB
Loading

docs/benchmark/benchmark_iphone7.png

118 KB
Loading
106 KB
Loading
124 KB
Loading
94.7 KB
Loading
-128 KB
Binary file not shown.
Loading

0 commit comments

Comments
 (0)