On Aug 22, 2008, at 10:34, Jeremias Maerki wrote:

On 22.08.2008 00:15:00 Andreas Delmelle wrote:
So, I was wondering about the role of the reference queue. Calling
poll() returns the first reference /if/ one is available, so it seems
likely that cleanSegment() does get called frequently enough, but
there's always the possibility that it returns without a reference
being available, yet. Or, as it happens, after throwing away only
roughly half of the references.
Maybe it's only those that are also effectively enqueued at the time
the cleanup is triggered (didn't try adding this to the stats yet).

Javadoc says about WeakReference that the queueing may happen at some
point after the reference is cleared. But a delay alone doesn't explain
that so many instances weren't cleared.

I got the impression that the cleaning wasn't done for some cache
segments at all because the threshold never got reached. Just a feeling.

Now I suddenly see it... Due to what you point out below, some entries in bucket #0 will be distributed over the reference queueS (plural) for segments #0, #8, #16 and #24, but each cleanup only takes care of one of those 4 segments (the one where the entry ended up that was last added in put()).

<snip />
Segments: always 32
Buckets: initially 8, rehash doubles the number of buckets each time

That doesn't match what you're saying. Initially, 4 segments would share
entries in 1 bucket. After a few rehashes, each segment would have its
entries in a set of buckets. I think that's why in your patch the
segment.count goes down into the negative (i.e. it's wrong).

Correct. No idea why I never saw that... :/

The effect of the count going into the negative follows from the fact that some stale entries will actually belong to another segment. The only other way around that would have been to always limit the number of segments to table.length [i.e. the segmentIndex for a lower number of buckets should actually have been something like: hash(o) & ((SEGMENT_COUNT - 1) & (table.length - 1))], so that all entries for one bucket always belong to the same segment. My patch unconditionally cleared the whole bucket, decreasing the count for the wrong segment.

Plus, the removal of the reference queue polling just queues up
references which are never cleared. I've fixed that locally.

Darn', I thought I had modified the constructor to not register the entry with the queue. Seems I undid that change at some point...



Reply via email to