为什么`String(描述:Class.self)`比`NSStringFromClass(Class.self)`慢?

时间:2019-03-17 11:45:32

标签: swift performance

请考虑以下程序:

import Foundation
import QuartzCore

class C: NSObject {}

func benchmark() {
    let swift1 = CACurrentMediaTime()
    let swiftString = String(describing: C.self)
    let swift2 = CACurrentMediaTime()

    let objc1 = CACurrentMediaTime()
    let objcString = NSStringFromClass(C.self)
    let objc2 = CACurrentMediaTime()

    let timeForSwiftString = swift2 - swift1
    let timeForObjcString = objc2 - objc1
    print("timeForSwiftString / timeForObjcString:", timeForSwiftString / timeForObjcString)
}

for _ in 0..<20 {
    benchmark()
}

输出将类似于

timeForSwiftString / timeForObjcString: 21.023079257409023
timeForSwiftString / timeForObjcString: 1.8032004909527086
timeForSwiftString / timeForObjcString: 2.929076507541501
timeForSwiftString / timeForObjcString: 3.1707763580662034
timeForSwiftString / timeForObjcString: 2.884789101770234
timeForSwiftString / timeForObjcString: 3.167761588431754
timeForSwiftString / timeForObjcString: 3.0066055331053776
timeForSwiftString / timeForObjcString: 3.0707174733951255
timeForSwiftString / timeForObjcString: 3.213085166384659
timeForSwiftString / timeForObjcString: 2.830997374357457
timeForSwiftString / timeForObjcString: 3.24157236450268
timeForSwiftString / timeForObjcString: 3.0462955824531646
timeForSwiftString / timeForObjcString: 2.887874789238326
timeForSwiftString / timeForObjcString: 3.1071486398963732
timeForSwiftString / timeForObjcString: 2.995876045716979
timeForSwiftString / timeForObjcString: 3.073833893272912
timeForSwiftString / timeForObjcString: 2.965068621921414
timeForSwiftString / timeForObjcString: 3.0622197750334306
timeForSwiftString / timeForObjcString: 3.0484172031541656
timeForSwiftString / timeForObjcString: 1.9362930766842597

第一次测量始终是最昂贵的(可能是由于某些懒惰的运行时操作所致),因此我们将其跳过。

所有其他测量结果都表明,速度较慢。

我还有一个demo project,其基准是从1000个不同的类中获取字符串,该字符串显示:

  • Swift的String(describing: Class.self)的运行速度比Objective-C的NSClassFromString(Class.self)慢(30..150μs与4..12μs)

  • 在每个新类上调用Swift的String(describing: Class.self)会越来越慢, 而Objective-C时间保持不变

对这种行为有什么想法吗?

2 个答案:

答案 0 :(得分:3)

  

可能是由于某些懒惰的运行时动作

请注意,由于各种原因(包括动态加载的库的解析),首次调用任何东西的速度都会变慢。

  

对这种行为有什么想法吗?

第一个猜测是String(describing:)任何值,弄清楚它是什么类型的值(描述中说明它测试是否符合三种不同的协议),然后调用适当的函数来描述值。但是NSStringFromClass仅采用Class值,该值在编译时检查,然后直接调用将类名作为字符串获取所需的运行时函数,而无需测试和分支该值的种类通过。

TLDR:更多的工作需要更多的时间,测试和分支会使您减速。

HTH

答案 1 :(得分:2)

您正在将苹果与汽车进行比较。

  • NSStringFromClass做的是非常具体的工作,仅涉及类类型,并且用于与Objective-C程序的动态性质有关的转换。

  • Swift中的
  • String(describing:)任何内容转换为字符串表示形式,并且仅用于(且适用于)调试。它不会用于任何面向用户的代码,并且任何有意义的程序操作都不会取决于它的输出。因此,它不会出现在已发布的应用程序中,并且它的速度没有影响。因此,您的问题不仅过早而且不必要地优化。 String(describing:)的速度并不重要。