ShouldRasterize = true Layer. shouldRasterize = true shouldRasterize = true
Real machine test
- Model tested: iPhone X
- Test machine system: iOS 13.3.1
- Test method: After the view is loaded, slide the 20 cells to the bottom and then immediately to the top, and repeat until the end of the experiment
- Test view:
UIView
1. Comparison of Instruments – Core Animation
shouldRasterize = false
shouldRasterize = true
2. The analysis
As can be seen from the frame rate in the second column of the figure, the frame rate is relatively stable at 59/60 after rasterization is enabled, while the frame rate before rasterization is around 56/57. The GPU utilization rate in the third column is more obvious, which is stable at around 25% after rasterization, while it is around 83% before rasterization
discuss
Rasterization looks great, but if used incorrectly it can lead to more consumption. Specific real-world tests of whether a particular view should be turned on are most convincing, such as whether a rasterization run with Core Animatin in Instruments improves performance. In addition, rasterization is cached, which means it takes up some extra memory, and a lot of rasterization also puts some stress on runtime memory
It is important to only enable it on layers that do not update the results of each frame frequently, otherwise frequent cache flusher will be triggered.
The following image dynamically sets the shadow color in the above example to a random value in the cellForRowAt method
Compared to the example above where rasterization was enabled, the GPU usage only increased by 2%-3% but the frame rate was still much lower. While it avoids rerendering every frame, rapid swiping frequently triggers redrawing of shadows and caching as cells refresh
In terms of performance optimization, if you don’t know if rasterization is going to work, the easiest way to do it is to use a PNG image (if the image isn’t too big). Here is a test of replacing a dynamically drawn shadow background with a PNG image
The test code
import UIKit
let cellHeight = CGFloat(90)
let screenWidth = UIScreen.main.bounds.width
let screenHeight = UIScreen.main.bounds.height
class TestViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let contentView = UITableView(frame: UIScreen.main.bounds, style: .grouped)
contentView.delegate = self
contentView.dataSource = self
contentView.register(TestTableCell.self, forCellReuseIdentifier: "Cell")
view.addSubview(contentView)
}
}
extension TestViewController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return cellHeight
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell".for: indexPath) as! TestTableCell
cell.update(title: "Cell \(indexPath.row)")
return cell
}
}
class TestTableCell: UITableViewCell {
lazy var blockView: UIView = {
let view = UIView(frame: CGRect(x: 12, y: 6, width: screenWidth-24, height: cellHeight-12))
view.layer.shadowColor = UIColor.black.cgColor
view.layer.shadowOffset = CGSize(width: 10, height: 10)
view.layer.shadowRadius = 10
view.layer.shadowOpacity = 1
view.layer.shouldRasterize = true
view.backgroundColor = .orange
return view
}()
lazy var backgroundImageView: UIImageView = {
let view = UIImageView(image: UIImage(named: "fit"))
return view
}()
lazy var titleLabel: UILabel = {
let label = UILabel(frame: CGRect.init(x: 12, y: 20, width: 300, height: 20))
returnlabel }() override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) contentView.addSubview(blockView) contentView.addSubview(titleLabel) } required init? (coder: NSCoder) { fatalError("init(coder:) has not been implemented")
}
func update(title: String) {
blockView.layer.shadowColor = Int.random(in: 0... 1) = = 0? UIColor.blue.cgColor : UIColor.orange.cgColor titleLabel.text = title } }Copy the code