当前位置 : 主页 > 手机开发 > ios >

ios – Swift Dictionary荒谬的内存使用

来源:互联网 收集:自由互联 发布时间:2021-06-11
我在我的一个应用程序中遇到了一个有趣的问题.多次访问字典时,我的应用程序的内存使用量在几秒钟内就会超过一千兆字节.以下是一些显示问题的示例代码. override func viewDidLoad() { l
我在我的一个应用程序中遇到了一个有趣的问题.多次访问字典时,我的应用程序的内存使用量在几秒钟内就会超过一千兆字节.以下是一些显示问题的示例代码.

override func viewDidLoad() {
        let dictionary = ["key1":"value1"]
        let nsKey: NSString = "key1"
        let swiftKey = nsKey as String
        for _ in 0 ... 10000000 {
            dictionary[swiftKey]
        }
    }

重复访问字典会导致内存爬升,直到循环结束.我查看了仪器并看到了大量的字符串分配.事实证明使用NSString是个问题.

将nsKey更改为swift字符串就像这样修复了问题:

let nsKey = "key1"

将字典更改为NSDictionary还可以解决此问题:

let dictionary: NSDictionary = ["key1":"value1"]

有谁知道为什么使用铸造的NSString访问字典会导致如此多的堆分配,除了上面描述的那些之外还有其他任何修复吗?

这是一些照片.看起来幕后的字符串被分配并设置为自动释放(或者我是否正在读取下面的数据错误?)这可能是为什么内存使用会不断分配然后在以后耗尽?如果这是真的,这应该被视为“错误”吗? OS X和iOS上都会出现此问题.

enter image description here

enter image description here

最好的解决方案是不要在这里桥接到NSString.只需使用Swift类型.或者,正如您所发现的,您可以使用Foundation类型(NSString和NSDictionary).桥接可能需要制作临时副本.

但是,在任何情况下,在这样的循环中,出于某种原因创建临时副本是非常常见的(即使您避免了这个特定问题).要解决这个问题,您需要在循环中消耗自动释放池.例如:

let dictionary = ["key1":"value1"]
let nsKey: NSString = "key1"
let swiftKey = nsKey as String
for _ in 0 ... 10000000 {
    autoreleasepool {         // <=== the scope of the current pool
        dictionary[swiftKey]
    }
}

添加它将使您的记忆保持稳定.这在Cocoa的大循环中是很常见的事情.否则,在从顶级方法返回之前,池不会被耗尽.

网友评论