0

CNContactStore.enumerateContactsWithFetchRequest can consume over a gigabyte of RAM where there are thousands of contacts to sift through. I'm only interested in discovering contacts with dates / birthdays set but can't figure out how to use the predicate to filter on these. I'd rather set a predicate and then only filter on the contacts that match. Is there any way to do this?

strangetimes
  • 4,953
  • 1
  • 34
  • 62
  • "CNContactStore.enumerateContactsWithFetchRequest can consume over a gigabyte of RAM" No, it can't. You are handed just one contact at a time, and if it isn't the one you want, you just drop it and go on to the next. That is the _entire point_ of an enumeration. – matt Sep 19 '20 at 22:01
  • @mat Except that it does. I didn't make this up, I just verified this by using Instruments. I'm going to try and use `@autoreleasepool` around the call to see if it helps, but it is in fact leaking memory or at least caching it elsewhere. Moreover, even if I ended up successfully releasing the excess memory, it still consumes 1.5GB+ for 1000 contacts easily (especially if the contacts have notes / thumbnails etc, even if I don't specify those keys). – strangetimes Sep 19 '20 at 22:08
  • Well, I'd like to see that code. I just ran `enumerateContacts` and Instruments doesn't show me _any_ difference between the amount of memory used and what happens if I don't run `enumerateContacts` in the first place (i.e. my app uses 1.5MB holding steady regardless). – matt Sep 19 '20 at 22:31
  • You might be confusing between amount of memory used and "actual allocated memory" - the actual allocated memory crosses the 1.5GB mark for me, while yes the "amount of memory used" remains around 150MB in my case. What I'm trying to limit is the amount of overall allocations / deallocations, as it seems for some users this amount either does not decrease immediately, or on iOS it crashes the app on older iPhone models (it's using far too much memory and perhaps the autorelease pool isn't releasing soon enough in some cases). – strangetimes Sep 19 '20 at 22:40
  • If there was instead a way to set a predicate on the birthday field, for instance, the overall memory allocation would in theory by "outside of process" and may not count against the limits Apple sets on third party apps. This memory usage also shows up in Activity Monitor for people where I've observed the the overall memory does not immediately clear - Address book behind the scenes may be using an internal cache, I don't know. Either way, I'd like to speed this up by supplying a predicate so it does this at a database level (on the Contact store). – strangetimes Sep 19 '20 at 22:42
  • Well, there isn't such a predicate. The way to do this is to enumerate using a fetch request with _no_ predicate. All I'm trying to do now is get past this idea that doing that is memory-intensive. – matt Sep 19 '20 at 22:43
  • Sure - but like I explained, it seems memory intensive for all the tests I've run against sample address book data obtained from users. In my case the memory used remains low, but I can see overall allocations / deallocations reach 1.5GB+ within 5 seconds for approximately 600 contacts. Doing this with 1500 contacts "consumed" 2.2GB within 5 seconds (with an equal amount of deallocation in my case). Still, I'd liked to limit what I am enumerating. There's no point enumerating 1500 contacts when only 2 have birthdays set. I guess the only thing left to do would be file a feature request. – strangetimes Sep 19 '20 at 22:47
  • What I'm saying is that _"consumed" 2.2GB within 5 seconds (with an equal amount of deallocation in my case)_ is not consumption. Sure, 2.2GB may have been allocated during the course of the enumeration, but it was also all deallocated; there was no time when all 2.2GB was held in memory _at once_. No one is going to crash from using too much memory just because you did an enumeration of the entire contacts database. – matt Sep 19 '20 at 22:55
  • Don't get me wrong — I'm not defending the Contacts Framework. I think it's junk, and I've thought so ever since it replaced the AddressBook Framework. I'm just saying that this particular accusation leveled at it doesn't seem to me to be correct. – matt Sep 19 '20 at 22:58
  • Poor choice of words on my part - except I'm partially adamant that I've seen, "with me own eyes", that for some of my users, this "2.5GB allocated memory" is simply not going away, at least not soon enough. Activity Monitor seems to blame the app for hoarding that much RAM, but in actual fact it's `CNContactStore` (verified). This may be a bug / leak (I've been working with the address book for years, I've reported similar leaks in the past). Irrespective of what this might be, the OP essentially was only to ask if there was a predicate I'm not seeing – strangetimes Sep 19 '20 at 23:01
  • And of course, I totally understand what you're saying :) Just thought I'd clarify the issue at hand. I've been unable to reproduce actual "consumption", and I'm assuming that the "overall allocations" are somehow leaking for a very small handful of users in my case, so the idea was to try and limit the number of contacts by applying a predicate. I've filed a radar for now, hoping for improved `predicate` support – strangetimes Sep 19 '20 at 23:04

0 Answers0