在 iOS 上访问 NSUserDefaults 是否便宜?
Is accessing NSUserDefaults on iOS considered cheap?
简而言之:是fast/cheap吗?将 NSUserDefaults 的值存储在内存中以加快访问是否有意义?
更长:比如说,我有大量的值要存储并从 NSUserDefaults 读取;需要经常访问(读取)这些值。
在下面的代码片段中,我初始化了一个私有存储 属性,并使其与相应的 NSUserDefaults 值保持同步 - 所以当我需要读取它时,我读取了 属性.
如果直接从默认值读取实际上很快,我显然会删除私有 属性。但我不确定。快吗?
private var _loggedIn = NSUserDefaults.standardUserDefaults().boolForKey("loggedIn")
public var loggedIn: Bool {
get {
return _loggedIn
}
set {
_loggedIn = newValue
NSUserDefaults.standardUserDefaults().setBool(newValue, forKey: "loggedIn")
NSUserDefaults.standardUserDefaults().synchronize()
}
}
为未来的读者澄清:问题是关于阅读,而不是writing/synchronizing,这是(如答案)不快也不便宜。
.synchronize()
在 setter 中被调用是有正当理由的——在我的特定情况下,立即同步它很重要,所以我为了逻辑完整性牺牲了性能。一般情况下,你应该考虑是否需要调用它——或者让系统选择合适的时间写入。
..事实上,现在我看了一下,我看到将存储的 属性 保持在片段中,将提供逻辑完整性(只要从其他地方访问通过 getter,而不是直接来自 userDefaults)。所以我也可以在这里避免 synchronizing
。
它不太可能对性能产生重大影响,但您可以自己使用 Instruments 对其进行分析,以确保性能影响可以忽略不计。
读书很便宜。有大量的缓存,一切都发生在 RAM 中。变异相对便宜,但系统仍然需要定期将内容存储到 non-volatile 内存(闪存上的 .plist 文件)。
显式同步并不便宜。它消耗时间和更多能量。
所以对于读取来说没问题,但是如果有很多写入,我仍然会在一个单独的容器中进行,并且只在需要时进行序列化。
我按照@mipadi 去年的建议使用 Instruments 进行了一些性能测试,我的结论是没有实质性差异。
正如我在上面的评论中指出的那样,检测我们希望立即完成哪些 NSUserDefaults
写入非常重要。只是在那些特殊情况下使用 synchronize 方法,否则让 iOS 处理该工作以获得更好的性能。
没关系,除非你使用 NSUserDefaults 作为数据库。 synchronize() 将写入完整的 plist 文件,因此如果您存储兆字节的数据,然后进行大量同步,性能 and/or 电池寿命将受到影响。
但也请检查这个问题:How often are NSUserDefaults synchronised?
一个有趣的细节是,当您的应用程序终止时,将写入用户默认值。有人可能会尝试如果您的程序在更改 NSUserdefaults 后立即崩溃会发生什么情况;如果这算作 "termination"。
简而言之:是fast/cheap吗?将 NSUserDefaults 的值存储在内存中以加快访问是否有意义?
更长:比如说,我有大量的值要存储并从 NSUserDefaults 读取;需要经常访问(读取)这些值。
在下面的代码片段中,我初始化了一个私有存储 属性,并使其与相应的 NSUserDefaults 值保持同步 - 所以当我需要读取它时,我读取了 属性.
如果直接从默认值读取实际上很快,我显然会删除私有 属性。但我不确定。快吗?
private var _loggedIn = NSUserDefaults.standardUserDefaults().boolForKey("loggedIn")
public var loggedIn: Bool {
get {
return _loggedIn
}
set {
_loggedIn = newValue
NSUserDefaults.standardUserDefaults().setBool(newValue, forKey: "loggedIn")
NSUserDefaults.standardUserDefaults().synchronize()
}
}
为未来的读者澄清:问题是关于阅读,而不是writing/synchronizing,这是(如答案)不快也不便宜。
.synchronize()
在 setter 中被调用是有正当理由的——在我的特定情况下,立即同步它很重要,所以我为了逻辑完整性牺牲了性能。一般情况下,你应该考虑是否需要调用它——或者让系统选择合适的时间写入。
..事实上,现在我看了一下,我看到将存储的 属性 保持在片段中,将提供逻辑完整性(只要从其他地方访问通过 getter,而不是直接来自 userDefaults)。所以我也可以在这里避免 synchronizing
。
它不太可能对性能产生重大影响,但您可以自己使用 Instruments 对其进行分析,以确保性能影响可以忽略不计。
读书很便宜。有大量的缓存,一切都发生在 RAM 中。变异相对便宜,但系统仍然需要定期将内容存储到 non-volatile 内存(闪存上的 .plist 文件)。
显式同步并不便宜。它消耗时间和更多能量。
所以对于读取来说没问题,但是如果有很多写入,我仍然会在一个单独的容器中进行,并且只在需要时进行序列化。
我按照@mipadi 去年的建议使用 Instruments 进行了一些性能测试,我的结论是没有实质性差异。
正如我在上面的评论中指出的那样,检测我们希望立即完成哪些 NSUserDefaults
写入非常重要。只是在那些特殊情况下使用 synchronize 方法,否则让 iOS 处理该工作以获得更好的性能。
没关系,除非你使用 NSUserDefaults 作为数据库。 synchronize() 将写入完整的 plist 文件,因此如果您存储兆字节的数据,然后进行大量同步,性能 and/or 电池寿命将受到影响。
但也请检查这个问题:How often are NSUserDefaults synchronised?
一个有趣的细节是,当您的应用程序终止时,将写入用户默认值。有人可能会尝试如果您的程序在更改 NSUserdefaults 后立即崩溃会发生什么情况;如果这算作 "termination"。