有人能给我简单解释一下ARC是如何工作的吗?我知道这和垃圾收集不同,但我只是想知道它是如何工作的。
此外,如果ARC在不妨碍性能的情况下运行GC,那么为什么Java使用GC?为什么它不使用弧线呢?
- 这会告诉你所有的clang.llvm.org:http://EN /文档/ automaticreferencecounting.html诀窍是要实现在Xcode和含5是在NDA。
- mbehan那可怜的建议"。我不想在我有一个帐户或登录还必须重新为中心的兴趣,但我knowing about nevertheless弧。
- does not do that弧GC does……一切你的工作,它与强和弱语义记忆和参考explicitly泄密,如果你把那些不好的。在我的经验,this is at first棘手当你使用块在Objective-C中,甚至在你和你的技巧learn of the left with some annoying(海事组织)在usages of many boilerplate代码块。这是更方便的强/弱references只是忘记它。moreover,GC可以做somewhat比wrt弧。CPU,but……更多的记忆。它可以是更快比显式存储管理,当你有很多的记忆。
- taylanub":"……更多的记忆"。很多人说,银行很难找到,但相信它。
- "the accepted回答:"mbehan here is to the多更好的答案的问题,虽然我。"is the accepted答案是错误的。
- jonharrop currently":我不记得我为什么说,老实说。结果:-),同时realized that there on the many different are such that知道GC策略worthless are probably在橡皮布的声明。让我从他的记忆背诵Hans Boehm和配置myths半truths:"为什么我dubious is this to地区民间wisdoms感?"
- 在消去偶的意见从2针that of giving超时是年人,但是about the which我提供的链接,我认为是非常有用的介绍to the subject:developer.apple.com /图书馆/ / /一般/含releasenotes & hellip;
每一个新开发人员来到Objective-C必须学习何时保留、释放和自动释放对象的严格规则。这些规则甚至指定了表示从方法返回的对象的保留计数的命名约定。一旦您将这些规则牢记在心并始终如一地应用它们,Objective-C中的内存管理就成了第二天性,但即使是最有经验的Cocoa开发人员也会时不时地出错。
使用Clang静态分析器,LLVM开发人员意识到这些规则足够可靠,他们可以构建一个工具来指出代码所采用的路径中的内存泄漏和过度释放。
自动参考计数(ARC)是下一个逻辑步骤。如果编译器能够识别应该在哪里保留和释放对象,为什么不让它为您插入代码呢?严格的、重复的任务是编译器和它们的兄弟们所擅长的。人类忘记了事情,犯了错误,但计算机更为一致。
然而,这并不能完全免除您对这些平台上内存管理的担忧。我在这里描述了我的答案中需要注意的主要问题(保留周期),这可能需要你稍微考虑一下以标记弱指针。但是,与你在ARC中获得的相比,这是次要的。
与手动内存管理和垃圾收集相比,ARC通过减少编写保留/释放代码的需要,而不是在垃圾收集环境中看到停止和锯齿形内存配置文件,为您提供了两个方面的最佳选择。垃圾收集相对于这一点的唯一优势是它处理保留周期的能力,以及原子属性分配便宜的事实(如本文所讨论的)。我知道我正在用ARC实现替换我现有的所有macgc代码。
至于这是否可以扩展到其他语言,它似乎与Objtovi-C中的引用计数系统相适应。很难将其应用于Java或其他语言,但我对低级编译器细节不太了解,无法在那里作出明确的声明。考虑到苹果是LLVM中推动这一努力的一方,除非另一方为此投入大量资源,否则Objective-C将首先出现。
这件事的揭幕震惊了WWDC的开发者,所以人们不知道这样的事情是可以做的。随着时间的推移,它可能会出现在其他平台上,但目前为止,它仅限于LLVM和Objective-C。
- 我的重点:这并不能完全免除你对内存管理的担忧。
- 谢谢你的回复。你能举个例子说明一下你需要手动管理内存吗?谢谢
- @用户635064-对于在ARC下仍然需要注意的内存管理条件,请参阅我在上面链接到的答案:stackoverflow.com/questions/6260256/…
- ARC真的是一项创新吗?根据你的回答,我得出结论,ARC是一个新概念,第一次用在目标C中(如果我错了,请纠正我)。老实说,我不是一个客观的C开发人员,对ARC不太了解,但是Boost共享指针(参见boost.org)是否完全相同?如果没有,有什么区别?
- @DMM——这是一个编译器级的过程,它扩展了整个语言,而不是依赖于重载的操作符(如boost)。此外,这使得将手动引用计数的应用程序转换为ARC变得容易。Boost处理局部变量的方式也可能与Arc不同,Arc知道局部变量不再被使用,并可以在此时释放。我相信通过boost,您仍然需要以某种方式指定变量。
- @布拉德-我明白了,谢谢你的澄清。将C++应用程序从原始切换到Boost共享指针确实不是微不足道的,更不用说不可能了。但你提到的最后一点并不是真的:你不需要显式地释放一个boost指针。指针本身驻留在堆栈上(或是嵌入的成员),因此将在作用域退出时删除它。然后,析构函数运行并执行智能指针欺骗。
- 为了回答"它是新的"问题,Delphi已经有了字符串、数组和接口的自动引用计数(用于COM支持)十多年了。我同意,在GC环境和"手动完成"环境之间,这确实是一个很好的折衷方案。我很高兴它在objc和llvm中(这样其他语言也可以利用它)。
- 苹果的ARC是否真的是创新,取决于你还可以考虑什么。例如,ansistings是在delphi和freepascal中自动计算的引用。ARC更通用,也更有限。客观主义比其他语言更需要它。
- 感谢您以如此清晰的方式解释ARC。我希望有更多的客观C/Xcode概念解释得如此清楚。
- @Bradrarson:"我相信通过boost,您仍然需要以某种方式指定变量已经完成了。"不,当局部变量超出范围时,智能指针的析构函数会减少它所指向的对象的引用计数,如果该计数已达到零,则对象本身会被销毁。
- @Thedmi:"ARC真的是一项创新吗?".automatic reference counting是1960年发明的,已经在许多语言中使用,如python和mathematica。它不在JVM或CLR中使用,因为它非常慢并且泄漏循环。
- @Bradrarson:"垃圾收集相对于这一点的唯一优势是它处理保留周期的能力,以及原子属性分配是便宜的这一事实。"跟踪垃圾收集器比基于作用域的引用计数快10倍。flyingfrogblog.blogspot.co.uk/2011/01/…
- ARC如何处理内存碎片?
- 显然,必须使用原子操作更新引用计数;否则,如果被多核系统上的多个线程访问,则可能会损坏引用计数。这会在核心之间产生大量的总线流量,因此速度可能非常慢。因此,对于运行在多核上的多线程软件来说,垃圾收集环境可能更快。
ARC只是在编译器确定何时调用RETAIN/RELEASE时播放旧的RETAIN/RELEASE(MRC)。与GC系统相比,它具有更高的性能、更低的峰值内存使用率和更可预测的性能。
另一方面,ARC(或MRC)不可能使用某些类型的数据结构,而GC可以处理它们。
例如,如果您有一个名为node的类,并且node有一个nsarray的子类,并且有一个对它的父类的引用,这个引用"只与gc一起工作"。使用ARC(以及手动参考计数),您会遇到问题。任何给定节点都将从其子节点和父节点引用。
像:
1 2
| A -> [B1, B2, B3]
B1 -> A, B2 -> A, B3 -> 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中是不可能实现的",我认为您的意思是没有提示,自动清理是不可能实现的;显然,数据结构是。
- 当然,但是只有objc对象的自动清理在arc下可用,所以"no automatic cleanup"=="no cleanup"。不过,我会在有更多时间的时候再修改答案。
- @条纹:相当于人工清除圆弧是人工打破周期,如foo = nil。
- "[ARC]将倾向于具有更高的性能……ARC将性能放在更大的优先级"。当众所周知引用计数比跟踪垃圾收集慢得多时,我很惊讶地看到这一点。flyingfrogblog.blogspot.co.uk/2011/01/…
- 理论上,GC速度更快(每个引用计数操作都必须是多处理器缓存一致的,而且其中有很多)。实际上,objc唯一可用的GC系统要慢得多。对于GC系统来说,在用户可察觉的时间内随机暂停线程也是非常常见的(有一些实时GC系统,但它们并不常见,我认为它们有"有趣的"约束)。
- @条纹:你不需要一个实时的GC来避免停顿。您只需要一个增量GC,这是20世纪70年代的技术。
- 这可能是20世纪70年代的技术,但在20世纪10年代,公司仍然提供平台,要么不使用增量GC,要么仍然遭受重大停顿。苹果公司仅仅10年前就发布了一个GC系统,但现在仍然如此(尽管他们现在告诉你不要使用它)。谷歌也做了同样的事情(除了他们不告诉你不要使用它,你不能在Android上避免它…除非你绕过Java)。在这两家公司中,如果可能的话,都有充分的理由去做正确的事情。也许比你想象的更难满足现实系统中的所有约束条件?
- 您能否通过提供一个具体的示例(带代码)来扩展您的答案,其中弱引用无法解决保留周期问题?你所写的对我来说并不清楚("例如,如果你有时会抓住b1,并期望通过父指针向上爬,找到a。如果你只抓住b1,a可以(通常也会)蒸发,并带走b2和b3。")
- 准确地说,用弱引用保存叶节点不会使父母存活。使用强引用时,所有节点都将始终保持活动状态。对于垃圾收集来说,持有一个叶子就足以使整个图形保持活动状态,如果您放开叶子,GC将注意到节点之间只引用了彼此,并将其全部释放。
- 弱引用会阻止保留循环,但它们不会让您(例如)具有父指针和子指针的对象图在没有外部引用之前保持整个图的活动状态。
魔术
但更具体地说,ARC的工作原理是:完全按照您对代码的处理方式(有一些细微的差异)。ARC是一种编译时技术,与GC不同,它是运行时的,会对性能产生负面影响。ARC将为您跟踪对对象的引用,并根据常规规则合成retain/release/autorelease方法。因为这个ARC也可以在不再需要的时候立即释放东西,而不是仅仅为了约定而将它们扔到自动释放池中。
其他一些改进包括将弱引用归零、自动将块复制到堆、全盘加速(自动释放池为6x!).
关于所有这些如何工作的更详细的讨论可以在ARC上的LLVM文档中找到。
- -1"ARC是一种编译时技术,与GC不同,它是运行时的,会对性能产生负面影响"。参考计数在运行时会被缓冲,这是非常低效的。这就是为什么像JVM和.NET这样的GCS跟踪要快得多的原因。
- @乔恩:你有这方面的证据吗?从我自己的阅读中,似乎新的RC算法的性能和M&S GC一样好或更好。
- @xryl669:GC手册(gc handbook.org)中有完整的解释。注意追踪!=并购。
它与垃圾收集大不相同。您是否看到警告,告诉您可能在不同的线路上泄漏对象?这些语句甚至告诉您在哪一行上分配了对象。这已经更进一步了,现在可以在适当的位置插入retain或release语句,比大多数程序员都好,几乎100%的时间。偶尔会有一些奇怪的保留对象实例需要您帮助解决。
苹果开发人员的文档解释得很好。阅读"ARC如何工作"
To make sure that instances don’t disappear while they are still needed, ARC tracks how many properties, constants, and variables are currently referring to each class instance. ARC will not deallocate an instance as long as at least one active reference to that instance still exists.
To make sure that instances don’t disappear while they are still needed, ARC tracks how many properties, constants, and variables are currently referring to each class instance. ARC will not deallocate an instance as long as at least one active reference to that instance still exists.
要了解垃圾收集和ARC之间的区别,请阅读以下内容