On Wed, Dec 11, 2019 at 1:59 PM John Huss <johnth...@gmail.com> wrote:

>
>
> On Wed, Dec 11, 2019 at 10:59 AM Andrus Adamchik <and...@objectstyle.org>
> wrote:
>
>>
>>
>> > On Dec 10, 2019, at 9:39 PM, John Huss <johnth...@gmail.com> wrote:
>> >
>> >> My projects are set up to use soft references using "
>> >> cayenne.server.object_retain_strategy=soft". I wouldn't expect this to
>> >> behave differently than weak under memory pressure, but my unit test
>> with
>> >> soft is not releasing this memory. I'll try running the test with
>> "weak"
>> >> and see if that changes it. And I'll look at your project (thanks for
>> >> that).
>> >>
>> >
>> > To clarify for future readers, we're talking about objects being
>> retained
>> > by this reference path:
>> > QueryCache -> cached_object -> ObjectContext ->
>> > other_objects_that_weren't_cached
>> >
>> > Sorry, I was wrong about the cause here. The persistent objects ARE
>> > released by the context's objectStore (whether using weak or soft). But
>> the
>> > context is still retaining a lot of extra memory. I'm having a hard time
>> > determining the specific cause. It might be the dataRowCache?
>>
>> If you have "Use Shared Cache" unchecked in the modeler, then you get a
>> single dataRowCache per context, so that would definitely explain it. I am
>> using the default - one dataRowCache per stack, shared by all contexts, so
>> that's never a problem.
>>
>
> I've narrowed it down - the "extra" memory being retained by the
> ObjectContext is: entries in ObjectStore.objectMap - but not DataObjects
> themselves (those get cleared), it's just the references to those objects:
> the mapping from ObjectId -> WeakReference. These entries stay present
> after the WeakReference is cleared. All those ObjectIds (though small) add
> up to a significant amount of memory over time. It looks like these are
> supposed to be cleared ReferenceMap.checkReferenceQueue(), which calls
> ReferenceQueue.poll() to find the cleared WeakReferences and remove those
> entries from the ObjectStore's objectMap. However, poll() doesn't ever seem
> to return any results (a cleared WeakReference). If I add in a call to
> ReferenceQueue.remove(5) manually (which will block for five milliseconds
> while it finds cleared references), it does return them and clear that
> memory. I need to read more about ReferenceQueue, but the current
> implementation of checkReferenceQueue() does not appear to be working since
> poll() never returns anything.
>

This is actually a timing problem, not a problem with poll().
checkReferenceQueue() would need to be called *after* the context is done
being used *and* the gc has occurred. As it currently is
checkReferenceQueue() is called while the context is being used, which can
help clear *some* memory that can be freed while in use, but doesn't help
after the context is unused (like when it is just sitting being referenced
by an object in the QueryCache.


>
>>
>> Andrus
>>
>>

Reply via email to