如何获取核心数据存储中存在的数据的总内存大小(以字节为单位)。如何获取特定数据行的内存大小。
答案 0 :(得分:6)
在iOS 7及更高版本上,由于SQLite日志文件,older answers不再适用于SQLite支持的持久存储。对于每个持久性存储文件,您需要获取SQLite文件本身的大小(例如Foo.sqlite
)和日志文件的大小(例如Foo.sqlite-wal
和{{1} })并添加大小以获得总数。这非常重要,因为很可能大部分数据实际上都在日志文件中。您可以使用Foo.sqlite-shm
获取每个文件的此信息。
如果您在模型和中使用二进制属性,则为任何这些属性启用了“允许外部存储”,它会变得更加复杂。在这种情况下,您需要找到所有外部存储文件并添加其大小。它们的位置没有记录,但应该位于找到SQLite文件的目录的子目录中。对于名为NSFileManager
的SQLite文件,查找名为Foo.sqlite
的目录,外部二进制文件将在那里。 由于没有记录,因此可能会在没有警告的情况下进行更改。
更好的方法 - 如果不是太晚 - 就是将持久性存储放在它自己的子目录中。不要将其放在文档目录中,而是在文档中创建一个新目录并将SQLite文件放在那里。也就是说,创建一个名为.Foo_SUPPORT/_EXTERNAL_DATA
的目录,并将data
放入其中。要添加大小,只需递归扫描Foo.sqlite
中的每个文件并添加大小。然后你会抓住所有东西,即使日记或外部二进制文件或iOS未来版本中的任何变化。使用data
的{{1}}或NSFileManager
方法进行扫描的好方法。
查找特定数据行的内存大小是一个非常不同的问题,并且没有通用的解决方案。任何对象实例的开销,加上您的属性,以及任何内部未记录的对象enumeratorAtPath:
可能会创建(包括实例变量和动态分配的内存)。它甚至不是固定值,因为可以动态分配和释放数据。只添加属性的大小很容易 - 只需运行它们并加上每个的大小(字符串长度,数据长度等),但这不是完整的图片。
答案 1 :(得分:2)
使用Swift 5,我想出了这个答案。它不仅获取存储和文件的大小,而且使用Apples ByteCountFormatter格式化数据大小。
public func getSqliteStoreSize(forPersistentContainerUrl storeUrl: URL) -> String {
do {
let size = try Data(contentsOf: storeUrl)
if size.count < 1 {
print("Size could not be determined.")
return ""
}
let bcf = ByteCountFormatter()
bcf.allowedUnits = [.useMB] // optional: restricts the units to MB only
bcf.countStyle = .file
let string = bcf.string(fromByteCount: Int64(size.count))
print(string)
return string
} catch {
print("Failed to get size of store: \(error)")
return ""
}
}
使用非常简单:
// Get Core Data storage size:
guard let storeUrl = self.managedObjectContext!.persistentStoreCoordinator!.persistentStores.first?.url else {
print("There is no store url")
return
}
print("The size of the store is: \(self.getSqliteStoreSize(forPersistentContainerUrl: storeUrl))")
此处的一个次要细节是确保您检查moc
和persistentStoreCoordinator
确实具有价值-就我而言,由于我是如何初始化它们的,所以我知道它们确实具有价值。
关于以上考虑了wal
和shm
文件的答案,您可以通过在URL后面附加一个字符串来检查这些文件:
let newFileName = storeUrl.absoluteString.appending("\("-wal")")
let newFileName2 = storeUrl.absoluteString.appending("\("-shm")")
print("The size of the wal is: \(self.getSqliteStoreSize(forPersistentContainerUrl: URL(string: newFileName)!))")
print("The size of the shm is: \(self.getSqliteStoreSize(forPersistentContainerUrl: URL(string: newFileName2)!))")
答案 2 :(得分:1)
- (void)reportFileSizeOfPersistentStores
{
NSArray *allStores = self.persistentStoreCoordinator.persistentStores;
NSFileManager *fileManager = [NSFileManager defaultManager];
for (NSPersistentStore *store in allStores)
{
NSString *filePath = store.URL.path;
NSDictionary *attributes = [fileManager attributesOfItemAtPath:filePath
error:nil];
NSString *fileSize = attributes[NSFileSize];
NSLog(@"FileSize:%@", fileSize);
}
}