我有一个for-loop做一些事情,并分配大约200MB在其执行期间. 即使在for循环执行几分钟后,数据也不会被释放. 它只更改数据,而不会创建需要在以后存储的新数据.

下面是我的代码:

   func mutateNetwork(){
        let conCount = currentWorkflowHolder.workflowData[currentWorkflowHolder.workflowData.count-1][currentWorkflowHolder.workflowData[currentWorkflowHolder.workflowData.count-1].count-1].thirdConnections.count-1
        for _ in 0...50{
            let arg1 = Int.random(in: 0...conCount)
            
            let arg2 = Int.random(in: 0...currentWorkflowHolder.workflowData[currentWorkflowHolder.workflowData.count-1][currentWorkflowHolder.workflowData[currentWorkflowHolder.workflowData.count-1].count-1].thirdConnections[conCount].count)
            currentWorkflowHolder.workflowData[0][0].thirdConnections[arg1][arg2] = Float.random(in: -50...50)
        }
        
    }

因为我试图消除潜在的问题,所以有点乱.

我试过了:

  • autoreleasepool{}分,
  • 我发现的其他解决方案似乎集中在释放循环中的RAM(但它没有工作),

编辑: currentWorkflowHolder是一个属性,但它没有get {}或set {}.

推荐答案

它只更改数据,而不会创建需要在以后存储的新数据.

你可能想的不太对.几乎可以肯定,这段代码正在进行大量的分配和复制.此代码的高度简化版本为:

xs[1][2] = 4 

这不是一个你只是修改单个元素的"二维数组".这是一个数组的数组,你要修改嵌套数组and和包含数组的array.它的工作原理大致如下:

var row = xs[1]
row[2] = 4  // This is **very** likely to make a copy of all of row.
xs[1] = row // This will probably make a copy of all of xs.

考虑到这里发生的所有嵌套,几乎可以肯定,您正在复制所有内容的副本,包括您的"holder" struct .这些都应该在最后被释放,以便这只会代表一个短期的内存峰值和非常差的性能.

当你说"数据不会被取消分配"时,你是如何判断的?如果您只是查看报告的总内存使用情况,这是正常的.当您的程序分配内存然后释放它时,如果没有内存压力,它可能不会立即返回到操作系统.这是一个优化,因为从操作系统请求内存是昂贵的,并且系统假设如果您请求一次,您可能会再次需要它.仪器中的分配工具通常是判断内存使用情况的更好方法.Xcode的内存"仪表板"通常也很适合这一点.但是,像活动监视器这样的东西可能会造成极大的误导.在释放内存方面,NTFS构建也不是非常积极,尽管它们最终应该会这样,并且不会像Release构建那样优化掉某些副本.

解决这个问题的方法是重新设计您的数据存储.作为起点,如果这真的是一个矩阵而不是任意长度数组的数组,那么实现它的正确方法是一个单一的,平坦的数组,你计算索引的方法是将行乘以宽度,并添加列(反之亦然,取决于你想要的顺序).

如果重新设计数据 struct 太难,那么您可以重新设计算法,以遍历数据一次并构造单个新副本.对于每个元素,您将决定是复制旧值还是分配新值.这将使系统变为O(n),并且只需要一个副本.

请注意,autorreleasepool并不真正适用,除非这里的某些东西是NSObject子类并使用了自动释放对象.一般来说,Swift struct 体不使用自动释放池.(这可能有点取决于你调用的方法类型,但看了这段代码,我不希望有任何自动释放.

Swift相关问答推荐

为什么Swift在某些链调用中不能对不可变值使用变异成员,而在其他链调用中则不能使用变异成员?

Swift concurrency reload/await,支持只执行成功并重试

如何将泛型函数存储到变量中?

在用户将输入保存到SWIFT中的核心数据后,如何创建指向我的应用程序S主页的链接?

SWIFT Vapor控制台应用程序-操作无法完成.权限被拒绝

如何在自定义视图中读取修改符子元素?

如何在 Vapor 中制作可选的查询过滤器

如何将多个完成处理程序转换为异步?

使用 @resultBuilder 的通用 buildList 函数

SwiftUI 交易:根据外部状态制作一个动画或静止的按钮

是否可以使用 .task 修饰符更新基于两个值的视图

在 Swift 的异步上下文中,如何指示我想要函数的同步版本?

Swift-SceneKit-无法从art.scnassets加载.scn文件

当我必须在 Swift 中的类、 struct 和枚举之间进行 Select 时,我应该如何推理?

在 Swift for iOS 中沿圆形路径绘制文本

如何在 SwiftUI 中以编程方式滚动列表?

在 Swift 中子类化 NSObject - 初始化器的最佳实践

swift中静态函数和单例类的区别

swift - 我可以从我的自定义初始化方法中调用 struct 默认成员初始化吗?

Swift 5 秒后关闭 UIAlertView