我想知道强(弱)引用管理是否(以及多少)对代码执行有影响,特别是在释放许多类可能具有弱引用的对象时。起初我把它误认为是ARC,但事实并非如此。
在同一主题上有类似的question,但是他们不会调查性能影响或尝试从中提取数字。
让我说清楚一点:我不以任何方式暗示ARC或强弱/弱势可能会对表现产生不良影响,或者说不会使用这个" 。我喜欢这个。我只是好奇它的效率,以及如何调整它的大小。
我已将这段代码放在一起,以了解强/弱引用对执行时间的性能影响。
import Foundation
class Experiment1Class {
weak var aClass: Experiment1Class?
}
class Experiment2Class {
var aClass: Experiment2Class?
}
var persistentClass: Experiment1Class? = Experiment1Class()
var nonWeakPersistentClass: Experiment2Class? = Experiment2Class()
var classHolder = [Experiment1Class]()
var nonWeakClassholder = [Experiment2Class]()
for _ in 1...1000 {
let aNewClass = Experiment1Class()
aNewClass.aClass = persistentClass
classHolder.append(aNewClass)
let someNewClass = Experiment2Class()
someNewClass.aClass = nonWeakPersistentClass
nonWeakClassholder.append(someNewClass)
}
let date = Date()
persistentClass = nil
let date2 = Date()
let someDate = Date()
nonWeakPersistentClass = nil
let someDate2 = Date()
let timeExperiment1 = date2.timeIntervalSince(date)
let timeExperiment2 = someDate2.timeIntervalSince(someDate)
print("Time: \(timeExperiment1)")
print("Time: \(timeExperiment2)")
这段代码只测量释放对象和设置为nil所有引用所花费的时间。
如果你在Playground(Xcode 8.3.1)中执行它,你会看到10:1的比例,但Playground执行比实际执行慢得多,所以我还建议用" Release&#执行上面的代码34;构建配置。
如果您在Release I中执行,建议您将迭代计数设置为" 1000000"至少,我这样做的方式:
通过这种测试,我相信绝对的结果毫无意义,我相信这对99%的常用应用都没有影响......
到目前为止,我的结果显示,在Mac上执行的Release配置:
Time: 3.99351119995117e-06
Time: 0.0
然而,在我的iPhone 7Plus中,在Release中执行相同的操作:
Time: 1.4960765838623e-05
Time: 1.01327896118164e-06
显然,此测试显示对典型应用程序的实际影响几乎没有任何顾虑。
以下是我的问题:
编辑1
我发现这个LinkedList测试非常有趣,原因如下:请考虑以下代码:
//: Playground - noun: a place where people can play
import Foundation
var n = 0
class LinkedList: CustomStringConvertible {
var count = n
weak var previous: LinkedList?
var next: LinkedList?
deinit {
// print("Muorte \(count)")
}
init() {
// print("Crea \(count)")
n += 1
}
var description: String {
get {
return "Node \(count)"
}
}
func recurseDesc() -> String {
return(description + " > " + (next?.recurseDesc() ?? "FIN"))
}
}
func test() {
var controlArray = [LinkedList]()
var measureArray = [LinkedList]()
var currentNode: LinkedList? = LinkedList()
controlArray.append(currentNode!)
measureArray.append(currentNode!)
var startingNode = currentNode
for _ in 1...31000 {
let newNode = LinkedList()
currentNode?.next = newNode
newNode.previous = currentNode!
currentNode = newNode
controlArray.append(newNode)
measureArray.append(newNode)
}
controlArray.removeAll()
measureArray.removeAll()
print("test!")
let date = Date()
currentNode = nil
let date2 = Date()
let someDate = Date()
startingNode = nil
let someDate2 = Date()
let timeExperiment1 = date2.timeIntervalSince(date)
let timeExperiment2 = someDate2.timeIntervalSince(someDate)
print("Time: \(timeExperiment1)")
print("Time: \(timeExperiment2)")
}
test()
我发现以下内容(在发布配置中运行):
我认为这个测试非常占用CPU,因为节点是一个接一个地释放的(如果你看到代码,只有下一个是强大的,前一个很弱)...所以一旦第一个被释放,其他人一个接一个地落下,但并非完全落下。
答案 0 :(得分:1)
实际上没有自动内存管理这样的东西。无论您是否使用ARC,内存都由retain
和release
管理。不同之处在于谁编写代码,您或编译器。有你写的手动内存管理代码,还有ARC写的手动内存管理代码。理论上,如果您正确地执行了此操作,ARC会在您的代码中完全插入相同的retain
和release
命令。因此,性能上的差异应该是微不足道的。