Recently I noticed that the performance of a scroll was slowing down. I tracked down the problem, and I found that the cause was a the use of font created by the UIFont(descriptor:size:) constructor. I changed that constructor for UIFont(name:size:) and my problems were solved.
I isolated the problem in a project. The code is:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var firstLabel: UILabel!
@IBOutlet weak var secondLabel: UILabel!
@IBAction func onStartTest(sender: AnyObject) {
startMeasurement()
let firstFont = UIFont(name: "Marker Felt", size: 16)
firstLabel.font = firstFont
finishMeasurement("UIFont(name)")
startMeasurement()
let secondFontDescriptor = UIFontDescriptor(name: "Marker Felt", size: 16)
let secondFont = UIFont(descriptor: secondFontDescriptor, size: 16)
secondLabel.font = secondFont
finishMeasurement("UIFont(descriptor)")
}
}
private var time: UInt64 = 0
public func startMeasurement() {
time = mach_absolute_time()
}
public func finishMeasurement(name: String) {
let duration = mach_absolute_time() - time
print("* \(name) \(duration)ns")
}
These are some of my measurements:
iPhone 4S - iOS 9.0.2
* UIFont(name) 111,300ns
* UIFont(descriptor) 112,420,263ns
iPhone 6S - iOS iOS 9.2
* UIFont(name) 134,247ns
* UIFont(descriptor) 17,047,707ns
Simulator - iOS 9.2
* UIFont(name) 1,971,106ns
* UIFont(descriptor) 485,208,205ns
Simulator - iOS 8.1
* UIFont(name) 9,946,584ns
* UIFont(descriptor) 1,957,802,431ns
Am I doing something wrong?
I asked an engineer at WWDC 2018, and he told me essentially this:
Descriptors are very very expensive because they are searching the ENTIRE system font library every single time for the characteristics you've provided. He told me that this search really isn't optimized and so should never be used in a scrolling situation and should really only be called once and then cached. It's doing this because you don't actually need to specify the font name but instead just various qualities of it and the system will provide you with something.
UIFont(name: size:)
however is very fast because it's going directly to the requested font in the system. It knows where the font is because you have given the full exact name and it can then just scale it. No other nice features.
It's roughly an O(n) operation vs an O(1)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With