use*_*064 206 cocoa-touch garbage-collection objective-c automatic-ref-counting
有人可以简单地向我解释ARC是如何工作的吗?我知道它与垃圾收集不同,但我只是想知道它是如何工作的.
此外,如果ARC在没有阻碍性能的情况下完成GC的工作,那么为什么Java使用GC?为什么不使用ARC呢?
Bra*_*son 244
每个来到Objective-C的新开发人员都必须学习何时保留,释放和自动释放对象的严格规则.这些规则甚至指定了命名约定,这些约定意味着从方法返回的对象的保留计数.一旦您将这些规则牢记并始终如一地应用它们,Objective-C中的内存管理就成为第二天性,但即使是最有经验的Cocoa开发人员也会不时地滑倒.
使用Clang静态分析器,LLVM开发人员意识到这些规则足够可靠,他们可以构建一个工具来指出代码所采用的路径中的内存泄漏和过度发布.
自动引用计数(ARC)是下一个合乎逻辑的步骤.如果编译器可以识别您应该保留和释放对象的位置,为什么不让它为您插入该代码?严格的,重复性的任务是编制者及其兄弟们所擅长的.人类会忘记事情并犯错误,但计算机更加一致.
但是,这并不能完全让您免于担心这些平台上的内存管理.我在这里的答案中描述了需要注意的主要问题(保留周期),这可能需要您仔细考虑标记弱指针.然而,与您在ARC中获得的相比,这是次要的.
与手动内存管理和垃圾收集相比,ARC通过减少编写保留/释放代码的需要,而不是在垃圾收集环境中看到暂停和锯齿内存配置文件,为您提供了两全其美的优势.现在唯一的优势垃圾收集有超过这个是它对付保留周期,事实上,原子属性分配是廉价的(所讨论的能力在这里).我知道我正在用ARC实现替换所有现有的Mac GC代码.
至于是否可以将其扩展到其他语言,它似乎围绕着Objective-C中的引用计数系统.将它应用于Java或其他语言可能很困难,但我对低级编译器细节知之甚少,无法在那里做出明确的声明.鉴于Apple是在LLVM中推动这项工作的人,所以Objective-C将首先出现,除非另一方承诺为此提供大量资源.
WWDC的这些震惊的开发人员揭幕,所以人们不知道可以做到这样的事情.随着时间的推移,它可能出现在其他平台上,但目前它仅限于LLVM和Objective-C.
Str*_*pes 24
ARC只是玩旧保留/释放(MRC),编译器确定何时调用保留/释放.与GC系统相比,它具有更高的性能,更低的峰值内存使用率和更可预测的性能.
另一方面,ARC(或MRC)无法使用某些类型的数据结构,而GC可以处理它们.
例如,如果您有一个名为node的类,并且node有一个NSArray子节点,并且对其父节点的单个引用"只适用于GC".使用ARC(以及手动引用计数),您会遇到问题.任何给定节点都将从其子节点以及其父节点引用.
喜欢:
A -> [B1, B2, B3]
B1 -> A, B2 -> A, B3 -> A
Run Code Online (Sandbox Code Playgroud)
当你使用A时(例如通过局部变量),一切都很好.
当你完成它(和B1/B2/B3)时,GC系统最终将决定从堆栈和CPU寄存器开始查看它可以找到的所有内容.它永远不会找到A,B1,B2,B3,因此它将最终确定它们并将内存循环到其他对象中.
当你使用ARC或MRC,并用A结束它的引用数为3(B1,B2和B3都引用它),而B1/B2/B3的引用数都是1(A的NSArray有一个引用每).因此,即使没有任何东西可以使用它们,所有这些对象仍然存在.
常见的解决方案是确定其中一个引用需要较弱(不参与引用计数).这适用于某些使用模式,例如,如果仅通过A引用B1/B2/B3.但是在其他模式中它会失败.例如,如果您有时会保持B1,并期望通过父指针向上爬回并找到A.如果您只保持B1,则使用弱引用,A可以(并且通常会)蒸发,并且取B2和B3用它.
有时这不是问题,但使用ARC/MRC非常难以使用复杂数据结构的一些非常有用和自然的方法.
因此,ARC针对GC目标的同类问题.然而,ARC使用的是一组比GC更有限的使用模式,所以如果你使用GC语言(比如Java)并将ARC这样的东西嫁接到它上面,一些程序将不再起作用(或者至少会产生大量废弃的内存) ,并可能导致严重的交换问题或内存不足或交换空间).
您还可以说ARC更重视性能(或可预测性),而GC则更加重视通用解决方案.因此,GC具有较少的可预测CPU /内存需求,并且性能(通常)低于ARC,但可以处理任何使用模式.对于许多常见的使用模式,ARC将更好地工作,但是对于一些(有效的!)使用模式,它将会崩溃并死亡.
魔法
但更具体地说,ARC 的工作原理与您对代码所做的完全一样(有一些细微的差别)。ARC 是一种编译时技术,与 GC 不同,GC 是运行时的,会对性能产生负面影响。ARC会为你跟踪对象的引用,并根据正常规则综合retain/release/autorelease方法。因此,ARC 还可以在不再需要时立即释放它们,而不是纯粹为了约定而将它们扔到自动释放池中。
其他一些改进包括将弱引用清零、自动将块复制到堆、全面加速(自动释放池为 6 倍!)。
有关这一切如何工作的更详细讨论可以在ARC 上的LLVM 文档中找到。