2012-09-06 6 views
9

이 문제가 있습니다. 코어 데이터에 이미지 데이터베이스가 있습니다. 모든 이미지 (약 80MB)를 가져 와서 NSMutableArray에 넣습니다. 객체가 올바르게 폴트됩니다코어 데이터 메모리 사용 및 메모리 경고

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]); 
} 

로그를 읽고, 내가 개체가 모두 제대로 악기를 사용하여, 그러나 를 오류가 발생한 것을 볼, I 메모리의 80메가바이트가 사용되는 것을 알 수있다. 이것이 코어 데이터가 결과를 캐시하고 이것이 필요할 때 메모리를 확보해야하는 이유라고 생각합니다. 하지만 메모리 경고를 시뮬레이트하면 아무런 반응이 없습니다. 80MB가 남아 있습니다. (예)

바이트

그래프 카테고리 라이브 # 생활 # 일시적인 전체 바이트 # 전체 # 할당 (인터넷/전체) 0 malloc에 ​​176,00 : -

악기를 보면 할당의 80메가바이트 많은 malloc에 ​​의해 사용됩니다 KB 8,59 MB 50 57 18,39 MB 107 % 0.00, % 0.00 0 Malloc 200,00 KB 8,204 42 460 98,05 MB 502 % 0.00, % 0.04 0 Malloc 168,00 KB 7,05 https://www.dropbox.com/s/du1b5a5wooif4w7/Call%20Tree.png

,691,363이 전체 호출 트리의 이미지에 대한 링크입니다 0.00

메가바이트 43 19 10,17 MB 62 % 0.00 %210

아이디어가 있으십니까? 고마워

+0

코어 데이터가 '메모리 경고 수준 2'에서 메모리를 해제 했습니까? 시나리오에서 메모리 충돌이 적게 발생할 수 있습니까? – brigadir

+0

메모리 경고 수준 2를 시뮬레이트하는 "마법 방법"이 있습니까? 아니면 "단순히"나는 메모리를 소비해야합니까? – LombaX

+0

시뮬레이션 방법을 모르겠습니다. 다른 "무거운"앱 (예를 들어 Appstore)을 실행하고 앱을 백그라운드로 유지하고 콘솔 로그와 Instruments 메모리 차트를 추적해야합니다. 'level 2' 경고가 콘솔에서 언급 될 것입니다 - 그래서 그 순간에 메모리 차트를보아야합니다. – brigadir

답변

9

좋아, 왜 그런지 알았어. 엔티티에 대한 페치 요청을하면 오류가 활성화되어 있어도 해당 엔티티의 모든 데이터가 메모리에로드됩니다. 큰 바이너리 데이터 포함. 하지만 요청에 따라 (당신이 속성에 액세스 할 때 오류가, NO, 데이터가 즉시 캐시에로드되지 않습니다 설정 [request setIncludesPropertyValues:NO]; : 당신의 NSFetchRequest에이 설정

1 : 이 사용하는 많은 방법을 해결할 수 있습니다 해고) 그러나 이것은 "문제"가 있습니다. 즉시 (다시 필요 없기 때문에을 사용하여 메모리를 비우고 싶기 때문에) 프로 폴리를 다시 폴트하려고해도 메모리는 해제되지 않습니다. managedObjectContext가 재설정 될 때까지 캐시는 활성 상태를 유지합니다.

이 더 낫다 : 별도의 엔티티로 데이터를 분할 할 수 있습니다

2. 필자의 경우에는 URL과 이미지 데이터라는 두 가지 속성 만있었습니다. 필자는 데이터를 1 : 1 관계로 2 개의 엔티티로 분할했다 : imagecache와 imagedata. "imagecache"엔티티 (url 속성 사용)의 모든 행에 대해 fetchRequest를 작성했으며 이전 솔루션과 마찬가지로 메모리가 캐시되지 않았습니다. propery imagecache.relationship.image가 올바르게 잘못되었습니다. 이 속성에 액세스하면 오류가 발생하고 캐시가 채워집니다. 그러나이 경우 "imagecache"개체 ("father"개체)에서 [self.managedObjectContext refreshObject:object mergeChanges:NO];을 수행하면 즉시 캐시와 메모리가 해제되어 imagecache.relationship.image 속성이 다시 손상됩니다. 주의 : [self.managedObjectContext refreshObject:object.relationship mergeChanges:NO]을 수행하면 "하위"오브젝트에서 수행하지 마십시오. 캐시가 해제되지 않습니다. 나는 이것이 당신이 관계를 횡단하는 이유라고 생각합니다.

3- 나는 이것이 학문적 인 질문이라고 말했고,이 문제에 대한 진정한 "하루 종일"해결책 (더 나은 성능과 덜 두통)은 핵심 데이터 데이터베이스 내부에 큰 데이터를 저장하는 것을 피하는 것입니다. 데이터를 파일로 저장하고 참조 (파일 경로) 만 저장하거나 iOS 5를 사용하면 핵심 데이터 모델의 "데이터"속성에 "외부 저장소 사용"을 설정할 수 있습니다. 이것은 당신을 위해 모든 일을 할 것입니다.

+1

이 문제에 대한 다른 해결책을 찾은 적이 있는지 궁금합니다. 불행히도, 솔루션 3을 사용할 수있는 큰 NSData 메모리 개체가 없습니다. 오히려지도에 주석으로 표시되는 수십만 개의 개체가 있습니다. 장치에서 메모리가 충분하지 않으면 표시되는 데이터의 양을 제한 할 수 있도록 데이터를 일괄 적으로 가져옵니다. 그러나 메모리 경고가 발생하고 refreshObject : mergeChanges :를 호출하면 언급 한대로 메모리가 영향을받지 않으며 결국 메모리 충돌이 발생합니다. 이견있는 사람? – horsejockey

0

나는 당신이 일괄 적으로 메모리에 적은 개체를로드해야한다고 생각합니다.

coredata가 출시 한 메모리가 백그라운드에서 발생하기 때문에 프로그램 할 필요가 없습니다. 나쁜 소식은 장면 뒤에서 발생하고 '마법처럼'기억을 씹을 수 있다는 것입니다.

주위에는 여러 가지 방법이 있습니다. 예를 들어 절대적으로 필요한 행만 선택하려면 조건자를 사용하십시오. 모든 것을 가져오고 하나씩 차례로 목록을 살펴 보려는 일반적인 호출을하지 마십시오. CoreData가 모든 객체를로드하려고 시도 할 때 일반 호출을 수행 할 때 충돌이 발생할 가능성이 높습니다.

+0

네, 제가 적용한 첫 번째 해결책은 필요한 데이터 만 가져 오는 것입니다. 이것은 주로 "학문적 인"질문입니다. 문서는 이것에 관해서는 명확하고 코어 데이터에 의해 캐시 관리가 이루어지며 모든 것이 장면 뒤에서 발생하지만 메모리가 부족한 경우 메모리는 무료라고합니다. 나는 메모리 경고 이후 코어 데이터에 의해 사용 된 메모리가 감소 할 것으로 예상했다. 이걸 보지 못했고, 내 코드에 뭔가 문제가 있다고 생각했습니다 ...! 나는 "내 눈으로"핵심 데이터가 메모리 부족 상황에서 메모리를 해제하고 싶습니다 :-) – LombaX

+0

그냥 업데이트 : (NSData 인스턴스를 할당하는 간단한 루프) 메모리를 차지하려했지만 코어 데이터가 메모리를 확보하지 못했습니다. 나는 100MB의 NSData를 할당 한 다음 200, 그 다음 300을 할당하여 앱이 다운 될 때까지 많은 시간을 보냈습니다. fetchrequest의 모든 데이터를 캐시하지 않고 캐시하는 것 같습니다. 내 범위에 도달하기 위해 다른 접근법을 사용할 수는 있지만 이상하게 보입니다. 그들이 RAM을 계속 사용한다면 오류 속성의 의미는 무엇입니까? – LombaX