2010-09-27 31 views
5

在开发者文档,它说:定期在长时间运行的后台线程上耗尽自动释放池的最佳方法?

如果您的应用程序或线程是长期存在的和潜在的产生有很多自动释放的对象,你应该定期排出,并创建自动释放池(如应用程序套件确实在主线);否则,自动释放的对象会累积并且内存占用量会增加。但是,如果您的分离线程不进行Cocoa调用,则不需要创建自动释放池。

我不知道该怎么办的最好方式,这是。我认为有几种方法可行,但不知道哪个是“最好”的。我目前有启动线程,并保持它在等待操作执行方法:

- (void)startThread 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    accessoryRunLoop = [NSRunLoop currentRunLoop]; 

    //Add a dummy port to avoid exiting the thread due to no ports being found 
    [accessoryRunLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode]; 

    while(accessoryThreadIsRunning) 
    { 
     //Keep the thread running until accessoryTheadIsRunning == NO 
     [accessoryRunLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; 
    } 

    [pool release]; 
} 

我的选择,我能想到的是:

1)添加计数器在while(accessoryThreadIsRunning),以便每50或100次将会耗尽自动释放池并创建一个新池。我每次在该线程中执行一个方法(使用performSelector:onThread :)时,我可以创建一个autorelease池,然后在方法结束时释放它。

3)制作一个计时器,以便一个池被排空,然后定期创建。

我认为选择1是最好的,但想知道是否有不同的方式,我应该这样做。谢谢!

+0

我认为在wwdc 10中有关于 – RolandasR 2010-09-27 19:25:16

回答

4

我会以简单的死亡开始,并在循环中的每一次通过创建/排空池。

如果它在性能分析过程中显示为瓶颈,请修复它。

保持简单直到分析表明需要复杂性。


我只是重新读你的问题,并意识到在我的答案完全骨头。如果你正在运行一个运行循环,那么应该自动为你管理一个自动释放池;它应该在循环的顶部创建一个池,并在每次循环结束时将其排空。

,如果您有其他的东西会在runloop之外,您只需要一个周期自己。是这样吗?

在任何情况下,是的,模式是:

while(...) { 
    ... create pool ... 
    ... do stuff ... 
    ... drain pool ... 
} 
+0

+1的讨论。自动释放速度很快。 http://www.mikeash.com/pyblog/autorelease-is-fast.html – kubi 2010-09-27 20:29:53

+0

+1不要忘记,应用程序的主循环会在每次事件之后耗尽池。如果苹果不认为这是一个性能问题,它可能不是。 – JeremyP 2010-09-28 09:10:34

+0

为了清楚起见,我应该在[accessoryRunLoop runMode:]之前alloc分配一个新的autorelease池,然后释放它?这是在iPhone上,所以非GC环境。 – Ned 2010-09-29 16:53:17

0

主线程的运行循环水渠在每次通过它的游泳池,因此它是有道理这样做对其他线程太多。如果您选择仅偶尔排空游泳池,则可能会有很多自动释放对象等待长时间释放。实际上,这取决于您在运行循环的每次通过时可以释放多少内存以及触发运行循环的频率。我总是喜欢在每次传递时耗尽它,因为它很容易,并且帮助我尽可能减少内存占用。

0

传统的方法是,每隔50次左右保留一个计数器并排空,但正如bbum所说,只需从每个循环排出池开始,然后从那里开始。或者你可以使用你需要的对象,而不是创建任何自动释放对象。(只是坚持清除工厂方法)尽管如此,请记住-release所有对象。

2

每次都排空。正如其他人所说的那样,一个自动释放池的流失很便宜。

此外不排水可以是非常昂贵的。如果你的自动释放池中有足够的东西导致分页,那么会导致磁盘I/O,并且磁盘I/O的字节数如果不是成百上千万次,那么运行链接列表调用发布的东西就会花费数百万倍。 (并且在没有分页的iOS系统上,等待autorelease的大量额外对象可能会导致内存低的警告,这可能会导致应用程序被迫退出,或者前台应用程序要释放一堆Nib视图或其他东西,那么它稍后必须重新创建...或者它可能会强制您的应用程序退出)。

即使您没有使用“足够”的额外内存来导致低内存警告或分页,您也会运行一个较大的待命列表。更多的内存访问将在您最新的自动释放项目和最旧的内容之间进行。在内存层次结构中,最老的自动释放项目现在远离更远的距离,因此您的发布可能会存在缓存未命中,而L1或L2缓存命中。所以可能成本高出100倍。此外,您将释放的内存(可能在缓存中很热)很可能已被其他对象重用。

因此,每50到100次执行一次autorelease可能不会成为过早的优化。

每个循环执行一次发布,然后如果显示为瓶颈,则每隔X次执行一次,并确保使速度更快。

相关问题