衡量强/弱ARC参考的影响-对执行时间的影响 [英] Measure strong/weak ARC references impact - Impact on execution time

查看:67
本文介绍了衡量强/弱ARC参考的影响-对执行时间的影响的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道强引用/弱引用管理是否(以及有多少)对代码执行有影响,特别是在释放许多类可能具有弱引用的对象时.起初我把它误认为是ARC,但事实并非如此.

I was wondering if (and how much) strong/weak references management have an impact on code execution, especially when freeing objects to which many classes might have a weak reference. At first I mistaken this for ARC, but it's not.

类似的问题在同一主题上,但是他们不调查性能影响或尝试从中提取一些数据.

There's a similar question on the same topic, however they don't investigate performance impact or try to pull a number out of it.

让我清楚一点:我丝毫不暗示ARC或强/弱可能会对性能产生不良影响,或者说不要使用".我喜欢这个.我只是想知道它的效率以及尺寸大小.

Let me be clear: I'm not, in any way, suggesting that ARC or strong/weak might have a bad impact on performance, or say "don't use this". I LOVE this. I'm just curious about how efficient it is, and how to size it.

我整理了这段代码,以了解强/弱引用对执行时间的性能影响.

I've put together this piece of code to get an idea of the performance impact of strong/weak references in execution time.

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)")

这段代码仅测量释放对象并将其所有引用设置为零所花费的时间.

This piece of code only measure the amount of time it takes to free an object and to set to nil all its references.

如果您在Playground(Xcode 8.3.1)中执行它,您将看到10:1的比率,但是Playground执行比实际执行要慢得多,因此我也建议您使用发布"构建配置来执行上述代码.

IF you execute it in Playground (Xcode 8.3.1) you will see a ratio of 10:1 but Playground execution is much slower than real execution, so I also suggest to execute the above code with "Release" build configuration.

如果您在Release中执行,建议您至少将迭代次数设置为"1000000",就像我做的那样:

If you execute in Release I suggest you set the iteration count to "1000000" at least, the way I did it:

  • 将上述代码插入文件test.swift
  • 从终端运行swiftc test.swift
  • 执行./test

通过这种测试,我相信绝对结果几乎没有意义,而且我认为这对99%的常用应用程序没有影响...

Being this kind of test, I believe the absolute results makes no to little sense, and I believe this has no impact on 99% of the usual apps...

到目前为止,我的结果显示在Mac上执行的Release配置中:

My results so far shows, on Release configuration executed on my Mac:

Time: 3.99351119995117e-06
Time: 0.0

但是,在我的iPhone 7Plus上,在Release中执行的是相同的操作:

However the same execution, in Release, on my iPhone 7Plus:

Time: 1.4960765838623e-05
Time: 1.01327896118164e-06

很明显,该测试表明,对典型应用程序的实际影响应该很少或根本不用担心.

Clearly this test shows there should be little to no concern for real impact on typical apps.

这是我的问题:

  • 您能想到其他方法来衡量强/弱引用对执行时间的影响吗? (我想知道系统为此采取了哪些策略来改进)
  • 还有哪些其他重要指标? (例如多线程优化或线程锁定)
  • 我该如何改善呢?

编辑1

出于某些原因,我发现此LinkedList测试非常有趣,请考虑以下代码:

I found this LinkedList test to be very interesting for a few reasons, consider the following code:

//: 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()

我发现了以下内容(在Release配置中运行):

I found the following (running in Release configuration):

  • 我无法在手机上运行约32000次迭代,deinit期间EXC_BAD_ACCESS崩溃了(是的,在DEINIT期间...这不是很奇怪)
  • 约32000次迭代的时间是0比0.06秒,这是巨大的!

我认为此测试非常占用CPU资源,因为节点是一个接一个地释放的(如果看到代码,则只有下一个是强的,前一个是弱的)...因此,一旦释放了第一个,则其他的则一个接一个地倒下,但不是完全倒下.

I think this test is very CPU intensive because nodes are freed one after the other (if you see the code, only the next one is strong, the previous is weak)... so once the first one is freed, the others fall one after the other, but not altogether.

推荐答案

实际上没有自动内存管理之类的东西.不管是否使用ARC,内存均由retainrelease管理.区别在于谁或谁或谁来编写代码.有编写的手动内存管理代码,还有ARC编写的手动内存管理代码.理论上,ARC将精确地插入到您的代码中,如果正确执行此操作,则会插入相同的retainrelease命令.因此,性能上的差异应该是ε-微小的.

There is really no such thing as automatic memory management. Memory is managed by retain and release regardless of whether you use ARC. The difference is who writes the code, you or the compiler. There is manual memory management code that you write, and there is manual memory management code that ARC writes. In theory, ARC inserts into your code exactly the same retain and release commands that you would have inserted if you had done this correctly. Therefore the difference in performance should be epsilon-tiny.

这篇关于衡量强/弱ARC参考的影响-对执行时间的影响的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆