简体   繁体   English

方便方法与init方法的内存使用

[英]Memory Usage on convenience method vs init method

Recently when I looked into iPhone memory management, I tried to compare the convenience method and init method on the same object. 最近当我研究iPhone内存管理时,我试图在同一个对象上比较方便方法和init方法。 For example, I have UIImageView where it displays a downloaded NSData: 例如,我有UIImageView,它显示下载的NSData:

Convenience method: 便利方法:

imageView.image = [UIImage imageWithData:[downloads dataAtIndex:0]];

init method: init方法:

UIImage *aImage = [[UIImage alloc] initWithData:[downloads dataAtIndex:0]];
imageView.image = aImage;
[aImage release];

When I try to go back and forth on the views to increase the memory usage and hit "Simulate Memory Warning", the memory usage for the app went from 20MB to 18MB with convenience method, and init method went from 20MB to 13MB immediately. 当我尝试在视图上来回增加内存使用量并点击“模拟内存警告”时,应用程序的内存使用率从20MB变为18MB,方便方法,init方法立即从20MB变为13MB。

I also waited and interacted with the app to give time on releasing on the convenience method's autorelease. 我也等待并与应用程序进行交互,以便在方便方法的自动释放上发布时间。 But it didn't drop much. 但它没有下降太多。

Other than the autorelease vs release, what else contributed the difference? 除了autorelease vs release之外,还有什么贡献出来的差异?

Your autoreleased objects created by the convenience methods will not be released until the containing autorelease pool is drained. 在排除包含自动释放池之前,不会释放由方便方法创建的自动释放对象。 It is advisable to wrap memory intensive operations inside of an NSAutoreleasePool block if you will be making heavy use of them. 如果你要大量使用它们,建议在NSAutoreleasePool块中包装内存密集型操作。

The only difference that could be causing this is that imageWithData: doesn't use the system image cache, while initWithData: does. 可能导致这种情况的唯一区别是imageWithData:不使用系统映像缓存,而initWithData:则使用系统映像缓存。 So maybe the image that's made with the initializer can release it's image data when it receives a memory warning since it can go back to the system cache, while the one that's created by the convenience method can't. 因此,使用初始化程序创建的图像可能会在收到内存警告时释放它的图像数据,因为它可以返回到系统缓存,而由方便方法创建的图像则不能。

Objects created with convenience methods are autoreleased, as I am sure you are aware. 使用便捷方法创建的对象是自动释放的,我相信你知道。 However, if you have no AutoReleasePool in the RunLoop where you are creating the image, then the object will be added to a non-existent pool, and never properly cleaned up. 但是,如果在创建映像的RunLoop中没有AutoReleasePool,则该对象将添加到不存在的池中,并且永远不会正确清理。 This may be the case if you are running in a thread, and have forgotten to create an AutoReleasePool for that thread. 如果您在一个线程中运行,并且忘记为该线程创建一个AutoReleasePool,则可能就是这种情况。

To verify if this is the case, you could run Instruments (Leaks) and see what it reports. 要验证是否是这种情况,您可以运行Instruments(Leaks)并查看它报告的内容。

Something that I have noticed is that with autoreleased objects, under memory pressure, there is a system GC that occurs with a noticeable performance hit if you don't release your pools in a timely fashion. 我注意到的一点是,对于自动释放的对象,在内存压力下,如果您没有及时释放池,则会出现系统GC,其性能会受到显着影响。

Also, using the init / release method allows your memory consumption in loops to remain flat, while using a autorelease pool creates spikes. 此外,使用init / release方法允许循环中的内存消耗保持不变,而使用自动释放池会产生峰值。 In some memory challenged contitions, the rapid increase of objects in the autorelease pool may cause your application to get booted before the system takes steps to clean up stuff like emails being open, mobile safari tabs, and iTunes stuff running. 在一些内存挑战的版本中,自动释放池中对象的快速增加可能会导致应用程序在系统采取措施清理电子邮件打开,移动safari选项卡和运行的iTunes内容之前启动。

Bottom line, I tend to use init more because it makes my application's memory consumption more consistent and I see fewer problems with getting booted randomly. 最重要的是,我更倾向于使用init,因为它使我的应用程序的内存消耗更加一致,并且我发现随机启动的问题更少。 The gradual increase in memory consumption lets the daemons clean up the system without killing my app. 内存消耗的逐渐增加使守护进程可以清理系统而不会杀死我的应用程序。 Finally, as somewhat of an aside, if you are using the @property keyword in your classes, you have to be careful with stuff like: 最后,如果你在课堂上使用@property关键字,你必须要小心:

myProperty = [NSMutableArray arrayWithCapacity:10];

Because what will happen is when the pool in your main.m class gets collected that item will be gone, causing a crash due to calling a method on a released object. 因为将要发生的事情是当main.m类中的池被收集时,该项将被消失,由于在已发布对象上调用方法而导致崩溃。 If you are setting it with @property (nonatomic, retain) you will want to use: 如果您使用@property(非原子,保留)进行设置,则需要使用:

self.myProperty = [NSMutableArray arrayWithCapacity:10];

to make sure it hangs around. 确保它挂在身边。 You can avoid all of that by just going with alloc init however. 但是,您可以通过使用alloc init来避免所有这些。 Just watch your reference counts to make sure you don't have double references causing memory leaks. 只需观察您的引用计数,以确保您没有引用内存泄漏的双重引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM