Tim... you seem to be agreeing with me, then, that this does have something to do with the Application, and you are also allowing for some redundancy in calculation and memory use, so, again, why not just store it in the Application's Context, where all this is taken care of automatically? I think Jerome's first instinct here may have been the most straightforward.

Barring that, how about calling the clearCache in the Application's release(), rather than stop()?

-Tal

Tim Peierls wrote:
I wouldn't recommend RRWL for this.

Since it's harmless to recompute the AnnotationInfos, I think just having an AnnotationUtils.clearCache method would work well. Call it whenever an Application stops, say. It's worth a little redundant computation to avoid having to deal with shared locks and liveness.

--tim

On Thu, Apr 9, 2009 at 2:22 PM, Tal Liron <tal.li...@threecrickets.com> wrote:
Oh, I didn't mean synchronizing the whole map. I actually didn't mean much beyond suggesting that we brainstorm a way to use WeakReferences as keys in this particular case. I still don't have a complete solution in mind.

Another idea: Perhaps we can use a ReentrantReadWrite lock around a simple WeakHashMap? Since this is a "99% read" situation, most requests won't need to acquire locks.

(
ConcurrentHashMap is actually a very complicated and delicately tuned class, and it would be anything but trivial for us to try to re-implement it using WeakReferences.)

I know there are generic 3rd party solutions to this, but I know we'd all prefer to use what Java 5 offers us right now. I'm sure we can cobble together something that performs well!

-Tal

Tim Peierls wrote:
Did you read my subsequent e-mail that talked about opening an issue to make this more robust? 

There is currently no standard concurrent map with weak keys, although MapMaker in Google Collections provides this and much more. An effort to put something like this into Java 7 is under way, but there's no telling whether it will actually happen.

Wrapping a WeakHashMap with synchronization is likely to be a performance bottleneck: every request has to grab a global lock. 

--tim

On Wed, Apr 8, 2009 at 2:06 PM, Tal Liron <tal.li...@threecrickets.com> wrote:

Hmm. I disagree that this has nothing to do with the Application. For example, if an Application is unloaded, this cached information will remain in the static field. In fact, there is no mechanism in place right now clean this cache, and in dynamic environments (possibly OSGi) it may accumulate "cruft." Not a huge problem, but this is the stuff memory leaks are made of...


Here's a thought: can we use a synchronized WeakHashMap here? That way, the AnnotationInfo would be discarded when the class is unloaded.


-Tal


Jerome Louvel wrote:

Hi all,
 
Beautiful! This new solution is available in SVN trunk.
 
Thanks Dave for the report and Tim for the clever fix!
 
Best regards,
Jerome
Louvel
--
Restlet ~ Founder and Lead developer ~
http://www.restlet.org
Noelios Technologies ~ Co-founder ~ http://www.noelios.com

 

De : tpeie...@gmail.com [mailto:tpeie...@gmail.com] De la part de Tim Peierls
Envoyé : mercredi 8 avril 2009 00:23
À : discuss@restlet.tigris.org
Objet : Re: ServerResource is currently incompatible with OSGi

Why involve Context at all? The AnnotationInfo associated with a Class<? extends UniformResource> does not depend on Context. You could just add a method to AnnotationUtils:

public static AnnotationInfo getAnnotationDescriptor(Class<? extends UniformResource > resourceClass) {
AnnotationInfo result = cache.get(resourceClass);
if (result == null) {
result = computeAnnotationDescriptor(resourceClass); // use code from existing getAnnotationDescriptors for this
AnnotationInfo prev = cache.putIfAbsent(resourceClass, result);
if (prev != null) result = prev;
}
return result;
}
private static final ConcurrentMap<Class<? extends Resource>, AnnotationInfo> cache =
new ConcurrentHashMap<Class<? extends Resource>, AnnotationInfo>();

Then you don't need getAnnotationDescriptors. You probably want a way to clear cache entries if a class is reloaded, say.

You could get more fancy, with Futures and such, but I think that would be wasted effort.

--tim


On Tue, Apr 7, 2009 at 1:20 PM, Tal Liron <tal.li...@threecrickets.com> wrote:
Ah, I can see your point now.

I would recommend, then, that a Context would have two separate ConcurrentHashMaps, something like this:

1. Context.getConfiguration() -- this would be for the user
2. Context.getImplementationCache() -- this would be for things like AnnotationUtils, and the user should not normally look at this, except perhaps for debugging

-Tal

David Fogel wrote:
Hi Tal-

I think what you suggested about appending a classloader id (perhaps
System.identityHashCode(cl) ?) would work.

Regarding the Restlet Context and this cache being "cruft":  You say
the Context is a reasonable place for information that applies to the
Application, but this doesn't have annotation cache doesn't have
anything to do with my Application, it's related to a hidden
_implementation_ detail.  As an end-user, we're not meant to be using
this annotion info cache directly.  Yet the Context, as a very
prominent and unavoidable part of the Restlet public API is meant to
be used and understood.  That's why I think it isn't a good place to
stash implementation-related data like this annotation stuff.

-Dave

------------------------------------------------------
http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=1572499
  



Reply via email to