Re: CoreData huge memory usage - is this right ?
Re: CoreData huge memory usage - is this right ?
- Subject: Re: CoreData huge memory usage - is this right ?
- From: Ben Trumbull <email@hidden>
- Date: Tue, 18 Dec 2007 17:46:18 -0800
Martin,
We recommend an import use its own MOC, and simply set the undo
manager on the MOC to nil. Easier, better, less filling.
The staleness interval has nothing to do with imports. It affects
the, well, staleness of cached data for faulting.
It's insufficient to drain the autorelease pool every 1000
iterations. You need to actually save the MOC, then drain the pool.
Until you save, the MOC needs to retain all the pending changes you've
made to the inserted objects. Losing changes just because somebody
popped an autorelease pool would be bad. This is documented in
several places, including the programming guide and -
setRetainsRegisteredObject:
There is an additional issue that complicates matters greatly under
the retain/release (not GC) memory model. Managed objects with
relationships nearly always create unreclaimable retain cycles.
Example:
Department <->> People
Department has a relationship to many people, and each person has an
inverse relationship to the department. Since these objects retain
each other, the retain game is over. This is a fundamental limitation
to retain counting.
To help alleviate this, Core Data allows you to turn a managed object
back into a fault. You can turn a specific object back into a fault
with -refreshObject:mergeChanges:NO (which shouldn't be called on a
managed object with unsaved changes pending). Or you can use the
sledge hammer, and just -reset the whole context. A big but not quite
that big hammer would be to call -registeredObjects on the MOC you
just saved, and then for (NSManagedObject* mo in registeredObjects)
{ [moc refreshObject:mo mergeChanges:NO] } This is a bit like reset,
but you can still re-use the managed objects themselves in the future.
As for why can't Core Data break the retain cycles for the objects you
no longer want (i.e. like -reset, but not everything), how would we
know ? We can't tell the difference between your UI/array controller/
whatever retaining an object, and an inverse relationship retaining
the object. It's trivial enough for you to grab the -
registeredObjects set, make a mutable copy, remove the objects you
want to preserve, and refresh the rest. And if you can't tell the
difference between the objects you want to preserve and those you want
to nuke, how could we ?
If you have concrete ideas for an API that would make this easier,
please file an enhancement request at bugreport.apple.com
The only meaningful difference between -reset and -release on the MOC
is whether or not you ever need to use that MOC object again. And,
now under GC, -reset is more immediate.
It may occur to some to ask why turning the object back into a fault
helps. Faults represent futures for unrealized/unmaterialized pieces
of a graph of connected objects. They don't retain anything as they
have no data, just an identity. A managed object that's in use has
data, and retains that data much in the same way any Cocoa object's
standard setter methods might work. The active pieces of the graph
are wired down, and the periphery are faults. Like a cloud. If you
turn enough of the center pieces of the cloud back into faults, you'll
have multiple distinct clouds instead (which is usually better)
MOC are not particularly expensive to create, so if you cache your
PSC, you can use different MOCs for different working sets or distinct
operations.
I can import millions of records in a stable 3MB of memory without
calling -reset.
- Ben
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden