gpt4 book ai didi

ios - 使用 Grand Central Dispatch 快速堆增长

转载 作者:塔克拉玛干 更新时间:2023-11-02 10:10:23 25 4
gpt4 key购买 nike

上下文:我有一个使用 GCD 的 iOS 游戏应用程序。对于应用程序,我有三个队列:主队列、游戏逻辑队列(自定义序列)、物理队列(自定义序列)。 Physics Queue 用于进行物理模拟,而 Game Queue 用于进行游戏逻辑。因此对于每次更新(每 1/60 秒),每个队列都完成各自的工作,然后通过在其他队列上调度 block 来与其他队列共享它。

问题:

使用 GCD: 当我玩游戏关卡时,即队列正在做一些工作时,我发现堆/分配的增长非常快,这导致应用程序因内存问题而崩溃。如果我退出关卡并进入非游戏 View ,即队列没有做任何工作,内存会慢慢下降(大约需要 2 分钟)并变得稳定。在所附的图像中,图像中的峰值就在我退出游戏关卡并出门之前。之后,随着对象被释放,内存会稳定下降。

没有 GCD: 如果我禁用其他两个队列并在主队列上运行所有内容,即我从我的代码中消除所有并发,我看不到任何显着的堆增长并且游戏运行正常.

已经在网上学习/尝试/研究过:我对 block 捕获和 block 被复制到堆的概念有一个简单的了解,但不是很确定。据我所知,当我退出游戏级别并进入非游戏 View 时,我无法在我的代码中找到任何这样的对象,所有预期被释放的对象都被释放。

问题:

  1. 带有 GCD 的应用程序创建了很多 block 。创建很多 block 是一种好的做法吗?
  2. 在运行仪器时,我发现快速分配但未释放的对象属于 Malloc 48 类别。这些对象的责任库是 libsystem_blocks.dylib,责任调用者是 _Block_copy_internal。一旦我退出游戏关卡,即当队列停止执行任何工作时,这些对象就会慢慢被释放。但是,重新分配非常缓慢,大约需要 2 分钟才能完全清理。有什么方法可以加速这种清理?我怀疑对象不断堆积,然后导致内存崩溃。

关于可能发生的事情有什么想法吗?

提前致谢。 enter image description here

根据以下评论的建议,我编写了以下测试代码。我基本上安排了从 CADisplayLink 的回调,然后在回调中我将 5000 个 block 安排到自定义队列中。

// In a simple bare-bones view controller template I wrote the following code

- (void)viewDidLoad
{
[super viewDidLoad];
self.objDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(loop:)];
[self.objDisplayLink setFrameInterval:1/60];
[self.objDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)loop:(CADisplayLink*)lobjDisplayLink
{
static int lintNumBlocks = 0;

if (lintNumBlocks < 5000)
{
dispatch_async(self.testQueueTwo,
^{
@autoreleasepool
{
NSLog(@"Block Number ; %d", lintNumBlocks);

int outerIndex = 1000;
while (outerIndex--)
{
NSLog(@"Printing (%d, %d)", outerIndex, lintNumBlocks);
}

dispatch_async(dispatch_get_main_queue(),
^{
@autoreleasepool
{
NSString* lstrString = [NSString stringWithFormat:@"Finished Block %d", lintNumBlocks];
self.objDisplayLabel.text = lstrString;
}
});
}
});

lintNumBlocks++;
}
else
{
self.objDisplayLabel.text = @"Finished Running all blocks";
[self.objDisplayLink invalidate];
}
}

此代码还提供了与上一篇文章中提到的 GCD 相同的堆增长。但令人惊讶的是,在这段代码中,内存永远不会下降到初始水平。仪器输出如下:

enter image description here

这段代码有什么问题?任何想法都会有所帮助。

最佳答案

当我让 CADisplayLink 每 60 秒触发一次时,我在 GCD 队列周围看到了同样类型的内存累积,但帧渲染 block 的完成时间比这要长。 block 将堆积在队列中,如您所见,它们会产生一些相关的开销。

Mike Ash 有 a great writeup about this ,他在其中展示了构建处理 block 的后果,以及减轻部分压力的方法。此外,最近关于 GCD 的 WWDC session 以及如何在 Instruments 中对此进行诊断都对此进行了介绍,但我现在找不到具体的 session 。

在我的例子中,我最终使用了类似于 Mike 的东西,我使用了一个调度信号量来防止内存中的 block 累积。我在 this answer 中描述了这种方法,连同代码。我所做的是使用最大计数为 1 的信号量,然后在分派(dispatch)新 block 之前检查它。如果该类型的另一个 block 位于串行队列中,我会保释并且不会将另一个 block 扔到堆上。一旦一个 block 完成执行,我就会减少信号量计数,以便可以添加另一个。

听起来您需要这样的东西来管理向队列添加新 block ,因为您希望能够在游戏负载增加时丢帧。

关于ios - 使用 Grand Central Dispatch 快速堆增长,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16229759/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com