核心数据内存使用情况和内存警告 [英] Core Data memory usage and Memory Warning

查看:169
本文介绍了核心数据内存使用情况和内存警告的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个问题。
我有一个Core Data中的图像数据库。
我获取所有图像(约80MB)并放入一个NSMutableArray。
对象正确错误:

I have this issue. I have a database of images in Core Data. I fetch all images (about 80MB) and put in an NSMutableArray. The objects are correctly faulted:

NSArray *fetchResults = [self.managedObjectContext executeFetchRequest:request error:&error];
self.cache = [NSMutableArray arrayWithArray:fetchResults];
for (ImageCache *imageObject in self.cache) {
    NSLog(@"Is fault? %i", [imageObject isFault]);
}

读取日志,我看到对象都正确错误
但是,使用Instruments,我看到使用了80MB的内存。
我认为这就是为什么Core Data缓存它的结果,并且应该在需要时释放内存。
但是(这是我的问题),如果我模拟内存警告,没有任何反应!

Reading the log, I see that the objects are all correctly faulted However, using Instruments, I see that 80MB of memory are used. I think this is why Core Data caches it's results, and should free the memory when it's needed. But (and this is my "problem"), if I simulate a memory warning, nothing happens! The 80MB remains there.

查看仪器 - 分配,许多Malloc使用80MB:(示例)

Looking at instruments - allocations, the 80MB are used by many Malloc: (example)

图类别Live Bytes#Living#Transitory Overall Bytes#Overall#Allocations(Net / Overall)
0 Malloc 176,00 KB 8,59 MB 50 57 18,39 MB 107%0.00, 0.00
0 Malloc 200,00 KB 8,20 MB 42 460 98,05 MB 502%0.00,%0.04
0 Malloc 168,00 KB 7,05 MB 43 19 10,17 MB 62%0.00 ,%0.00

Graph Category Live Bytes # Living # Transitory Overall Bytes # Overall # Allocations (Net / Overall) 0 Malloc 176,00 KB 8,59 MB 50 57 18,39 MB 107 %0.00, %0.00 0 Malloc 200,00 KB 8,20 MB 42 460 98,05 MB 502 %0.00, %0.04 0 Malloc 168,00 KB 7,05 MB 43 19 10,17 MB 62 %0.00, %0.00

这是指向整个呼叫树的图像的链接: https://www.dropbox.com/s/du1b5a5wooif4w7/Call%20Tree.png

This is a link to an image of the entire Call Tree: https://www.dropbox.com/s/du1b5a5wooif4w7/Call%20Tree.png

任何想法?感谢

推荐答案

好吧,我明白为什么会发生。当对实体发出读取请求时,即使启用了故障,该实体的所有数据也将加载到内存中。包括大二进制数据。
您可以使用许多方法解决这个问题:

Ok, I've understood why it happens. When you make a fetch request for an entity, even if the faulting is enabled, ALL DATA of that entity are loaded into memory. Including big binary data. You can solve this using many methods:

1-在您的 NSFetchRequest c $ c> [request setIncludesPropertyValues:NO];
设置NO,数据不会立即加载到缓存中,而只是在请求时(当您访问属性并且故障被触发时)
但是这有一个问题。即使你再次尝试故障属性(因为你不需要它立即,并要释放内存,使用 [self.managedObjectContext refreshObject:object mergeChanges:NO]; ),内存不会释放。缓存保持活动状态,直到managedObjectContext重置。

1- setting this on your NSFetchRequest: [request setIncludesPropertyValues:NO]; setting NO, the data are not loaded into the cache immediately, but only upon request (when you access the property and the fault is fired) But this have a "problem". Even if you try to fault again the propery (because you don't need it immediately and want to free the memory, using [self.managedObjectContext refreshObject:object mergeChanges:NO];), the memory is not freed. The cache stay alive until the managedObjectContext is reset.

这更好:

数据分成单独的实体。在我的情况下,我只有2个属性:url和图像数据。我将数据分成2个具有1:1关系的实体:imagecache和imagedata。
为imagecache实体(具有url属性)的所有行创建fetchRequest,并且像之前的解决方案没有缓存内存。正确的imagecache.relationship.image是正确的错误。访问此属性会导致故障触发,并且缓存将被填充。
但是在这种情况下,在imagecache对象(父对象)上执行 [self.managedObjectContext refreshObject:object mergeChanges:NO]; 在立即释放缓存和内存,再次故障imagecache.relationship.image属性。注意:不要对child对象,如果你做 [self.managedObjectContext refreshObject:object.relationship mergeChanges:NO] ,由于某种原因缓存不是释放。我认为这就是为什么你遍历的关系。

2- you can split your data into separate entities. In my case I had only 2 properties: an url and image data. I splitted the data into 2 entities with a 1:1 relationship: imagecache and imagedata. Made a fetchRequest for all the row of the "imagecache" entity (with the url property), and like the previous solution no memory was cached. The propery imagecache.relationship.image was correctly faulted. Accessing this property caused the fault to fire and the cache to be filled. But in this case, doing [self.managedObjectContext refreshObject:object mergeChanges:NO]; on the "imagecache" object (the "father" object), resulted in immediately freeing the cache and the memory, faulting again imagecache.relationship.image property. Attention: Don't do on the "child" object, if you do [self.managedObjectContext refreshObject:object.relationship mergeChanges:NO], for some reason the cache is not freed. I think this is why you traverse the relationship.

3-我说这主要是一个学术问题,真正的一天解决方案(更好的性能和更少的头痛)这个问题是为了避免在核心数据库中保存大数据。您可以将数据保存为文件,并仅存储引用(文件路径),或者使用iOS 5,您可以在核心数据模型中的任何数据属性上设置使用外部存储。这将为你做所有的工作。

3- I said this was mainly an academic question, the real "all day" solution (better performance and less headache) for this issues is to avoid saving big data inside core data database. You can save your data as files and store only a reference (filepath) or, with iOS 5 you have the possibility to set "use external storage" on any "Data" property inside your core data model. This will do all the work for you.

这篇关于核心数据内存使用情况和内存警告的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆