I guess we'll be having a look at this in detail .....

Werner

> -----Ursprüngliche Nachricht-----
> Von: Simon Lord [mailto:[EMAIL PROTECTED]
> Gesendet: Donnerstag, 15. März 2007 16:36
> An: [email protected]
> Betreff: Re: AW: AW: [castor-user] [XML] XMLClassDescriptorResolver
> XMLFieldDescriptorImpl cache possible memory leak
> 
> Werner,
> 
> My test program on jira (http://jira.codehaus.org/browse/CASTOR-1910)
> creates a single resolver and is only one thread therefor i do not
> synchronize access to it for the test - and still it eats memory!
> 
> However, i've seen that the number of descriptors does change over time
> (shown in jProfiler) even though my test is using the same bit of xml
> each time - so if the number of desriptors is changing then the cache is
> still being *written* to and read from therefor not 100% thread safe.
> 
> e.g., after 60 iterations (each iteration is 100 marshal and unmarshals)
> of my test app  (with -Xms128M -Xmx512M) there are 1.9 million instances
> of XMLFieldDescriptorImpl taking up 156Mb of memory!
> 
> Iteration 50 : 15328 millis         [u:93    m:93    f:68    t:508]
> Iteration 51 : 15703 millis         [u:94    m:94    f:66    t:508]
> Iteration 52 : 16344 millis         [u:67    m:67    f:63    t:508]
> Iteration 53 : 20375 millis         [u:97    m:97    f:67    t:508]
> Iteration 54 : 19578 millis         [u:130    m:130    f:35    t:508]
> Iteration 55 : 27015 millis         [u:68    m:68    f:33    t:508]
> Iteration 56 : 30672 millis         [u:237    m:237    f:30    t:508]
> Iteration 57 : 27985 millis         [u:107    m:107    f:27    t:508]
> Iteration 58 : 28188 millis         [u:142    m:142    f:2    t:508]
> Iteration 59 : 38953 millis         [u:178    m:178    f:1    t:508]
> Iteration 60 : 43844 millis         [u:257    m:257    f:0    t:508]
> Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
> 
> not to mention the time for the iterations!!
> 
> 
> Thanks
> 
> Simon Lord
> 
> 
> 
> 
> 
> Werner Guttmann wrote:
> > Simon,
> >
> > Please see inline.
> >
> > Werner
> >
> >> -----Ursprüngliche Nachricht-----
> >> Von: Simon Lord [mailto:[EMAIL PROTECTED]
> >> Gesendet: Donnerstag, 15. März 2007 16:03
> >> An: [email protected]
> >> Betreff: Re: AW: [castor-user] [XML] XMLClassDescriptorResolver
> >> XMLFieldDescriptorImpl cache possible memory leak
> >>
> >> Hi there,
> >>
> >> I've attached my small eclipse project to the JIRA issue i created:
> >> http://jira.codehaus.org/browse/CASTOR-1910
> >>
> >> Yes i was using the default memory in the test that i posted. The fact
> >> is though that after the first iteration the memory should (in my mind)
> >> stay the same as it's *exactly* the same piece of xml on the next
> >> iteration - so it should need to load more descriptors.
> >>
> >> Setting the memory to something larger doesn't fix the problem it just
> >> takes a little longer to run out of memory! As it never 'levels off'
> >> anywhere.
> >>
> >> The cache of descriptors inside XMLClassDescriptorResolverImpl.java
> uses
> >> java.util.HashMap which is known to not be thread safe
> >> (http://java.sun.com/j2se/1.5.0/docs/api/java/util/HashMap.html) as
> it's
> >> not synchronized. Whether that matters or not with the way the resolver
> >> is used/setup i do not know - but i'd rather play it safe and use it in
> >> a thread safe fashion ;-)
> >
> > I think our desire to play it (over-ambitiously thread-safe) is actually
> causing the problem here. Let me just repeat what Leander just said below:
> >
> >>> However, in my opinion XMLClassDescriptorResolver does not need to be
> >>> thread safe. Only the initial initialization of such a resolver
> instance
> >>> needs to be thread safe. Later, whenever you use that instance in
> >>> marshaller and unmarshaller instances, they will only use the resolver
> >>> in a "read-only" way, and not modify the resolver, thus no thread
> >>> synchronization is neccessary. Right?
> >
> > There's two distinctive phases in the life-cycle of an
> XMLClassdescriptorResolver:
> >
> > a) initialization.
> > b) usage for (un)marshalling.
> >
> > Once a) has been completed, b) is 100% thread-safe. In other words, the
> usage of one (and only one) XMLClassDescriptorResolver for your multi-
> threaded application is 100% okay. You just need to makes sure that
> initialization happens *before* usage.
> >
> >> Let me know how you get on.
> >>
> >>
> >> Thanks
> >>
> >> Simon Lord
> >>
> >>
> >> M.-Leander Reimer wrote:
> >>> Hello Simon,
> >>>
> >>> I am curious now, because I am also using the
> XMLClassDescriptorResolver
> >>> approach and our application that has many threads where unmarshalling
> >>> and marshalling happens, and I would like to know whether there is a
> >>> problem with that approach.
> >>>
> >>> However, in my opinion XMLClassDescriptorResolver does not need to be
> >>> thread safe. Only the initial initialization of such a resolver
> instance
> >>> needs to be thread safe. Later, whenever you use that instance in
> >>> marshaller and unmarshaller instances, they will only use the resolver
> >>> in a "read-only" way, and not modify the resolver, thus no thread
> >>> synchronization is neccessary. Right?
> >>>
> >>> Regarding your tests and the possible memory leak. Obviously, caching
> >>> things will require more memory. I am curious about your JVM settings
> >>> for the test that used the resolver. Have you increased the heap size
> or
> >>> did you run with the default 64MB?
> >>>
> >>>  > Iteration 7 : 6984 millis         [u:31    m:31    f:5    t:63]
> >>>
> >>> Total memory is at 63, so I guess the garbage collector kicked in,
> thus
> >>> the increase in time, but no more memory was available, thus the
> error.
> >>>
> >>> Still I would like to see your unit test, and perhaps I will also do a
> >>> little testing with my implementation to check the memory consumption.
> >>>
> >>> Regards,
> >>> Leander
> >>>
> >>>
> >>>
> >>> Simon Lord schrieb:
> >>>> Hello again Werner,
> >>>>
> >>>> Thanks for the reply.
> >>>>
> >>>> In the application i help to develop it is impossible for us to use
> >> only
> >>>> one resolver, as we have many threads needing to perform
> >> (un)marshalling
> >>>> operations and the implementation of XMLClassDescriptorResolver is
> not
> >>>> thread safe (it uses HashMaps) and we cannot afford to block until
> the
> >>>> resolver is available.
> >>>>
> >>>> However, i've spent a little time creating a unit test that i believe
> >>>> shows the symptoms of a memory leak. It also shows that using the
> >>>> resolver does not speed up the (un)marshaling, in fact slowing it
> down
> >> a
> >>>> touch.
> >>>>
> >>>> The test makes ten iterations of 100 unmarshals then marshals of the
> >>>> same bit of xml. Without a resolver the test completes but with the
> >>>> resolver the test fails on the 7th iteration with a java heap space
> >>>> exception.
> >>>>
> >>>> I'm going to create new issue on JIRA where i can attach source and
> >>>> jars or a zip of the eclipse projct i've created if that easier, to
> >> avoid
> >>>> sending them to everyone on this list.
> >>>>
> >>>> Here is the output from my test:
> >>>>
> >>>> u = avg unmarshal time (millis)
> >>>> m = avg marshal time (millis)
> >>>> f = free mem (mb)
> >>>> t = total mem (mb)
> >>>>
> >>>>
> >>>> Test setup: 10 of 100 unmarshal then marshal, useResolver = false
> >>>> Iteration 1 : 2047 millis         [u:13    m:13    f:0    t:1]
> >>>> Iteration 2 : 1265 millis         [u:7    m:7    f:1    t:1]
> >>>> Iteration 3 : 1250 millis         [u:6    m:6    f:0    t:1]
> >>>> Iteration 4 : 1188 millis         [u:7    m:7    f:0    t:1]
> >>>> Iteration 5 : 1219 millis         [u:6    m:6    f:0    t:1]
> >>>> Iteration 6 : 1171 millis         [u:6    m:6    f:0    t:1]
> >>>> Iteration 7 : 1204 millis         [u:6    m:6    f:0    t:1]
> >>>> Iteration 8 : 1234 millis         [u:6    m:6    f:1    t:1]
> >>>> Iteration 9 : 1156 millis         [u:6    m:6    f:0    t:1]
> >>>> Iteration 10 : 1203 millis         [u:6    m:6    f:1    t:1]
> >>>> Completed successfully
> >>>>
> >>>> Test setup: 10 of 100 unmarshal then marshal, useResolver = true
> >>>> Iteration 1 : 1235 millis         [u:6    m:6    f:3    t:13]
> >>>> Iteration 2 : 1265 millis         [u:8    m:8    f:1    t:20]
> >>>> Iteration 3 : 1532 millis         [u:6    m:6    f:7    t:32]
> >>>> Iteration 4 : 1890 millis         [u:11    m:11    f:18    t:54]
> >>>> Iteration 5 : 1797 millis         [u:7    m:7    f:10    t:54]
> >>>> Iteration 6 : 2047 millis         [u:11    m:11    f:3    t:54]
> >>>> Iteration 7 : 6984 millis         [u:31    m:31    f:5    t:63]
> >>>> Exception in thread "main" java.lang.OutOfMemoryError: Java heap
> space
> >>>>
> >>>>
> >>>> Thank you for your time
> >>>>
> >>>> Simon Lord
> >>>>
> >>>>
> >>>>
> >>>>
> >>>> Werner Guttmann wrote:
> >>>>> Hmm, you should *not* be creating a resolver for each root class,
> but
> >>>>> one resolver only for all classes potentially used throughout your
> >>>>> (un)marshalling operations. Once the resolver has loaded - in your
> >>>>> case - the descriptors for all classes found in that package, it
> will
> >>>>> cache them.
> >>>>> And the Unmarshaller will be able to retrieve the cached descriptors
> >>>>> as needed.
> >>>>>
> >>>>> I hope this explains things in more detail.
> >>>>>
> >>>>> Werner
> >>>>>
> >>>>>> -----Ursprüngliche Nachricht-----
> >>>>>> Von: Simon Lord [mailto:[EMAIL PROTECTED]
> >>>>>> Gesendet: Donnerstag, 15. März 2007 10:22
> >>>>>> An: [email protected]
> >>>>>> Betreff: Re: [castor-user] [XML] XMLClassDescriptorResolver
> >>>>>> XMLFieldDescriptorImpl cache possible memory leak
> >>>>>>
> >>>>>> Hi Steven,
> >>>>>>
> >>>>>> Thanks for your speedy reply.
> >>>>>>
> >>>>>> I understand that there is an object graph underneath the root
> >> object,
> >>>>>> hense i understand it needs to load the 3828 descriptors for the
> >> object
> >>>>>> graph underneath my root object. What i don't understand is why
> when
> >>>>>> marshalling/unmarshalling the same root class (albeit with possibly
> >>>>>> different values e.g., two objects of type person might have
> >> different
> >>>>>> names but it's still the same name field) the resolver is loading
> >> more
> >>>>>> descriptors but should in my opinion be using the same descriptors,
> >> it
> >>>>>> is only the values that have changed not the class/fields. I
> >> understand
> >>>>>> that in a complex object graph it may need to load more descriptors
> >> for
> >>>>>> different objects due to it having a larger object graph - but my
> >>>>>> object
> >>>>>> is staying relatively similiar each time - therefor i would expect
> >> some
> >>>>>> growth but not constant growth with each iteration.
> >>>>>>
> >>>>>> Also i'm not trying to create a resolver for every class - i'm
> >> creating
> >>>>>> a resolver for each root class and reusing them (and yes i am
> setting
> >>>>>> the resolver on the marshaller/unmashaller ;-). I don't think it is
> >>>>>> thread safe either - so i've implemented it in a thread safe manner
> >>>>>>
> >>>>>> I hope this sounds more like i'm implementing/understanding it all
> in
> >>>>>> the right way.
> >>>>>>
> >>>>>> I'm off to write a unit test now and do some further investigation
> :)
> >>>>>>
> >>>>>> Thanks
> >>>>>>
> >>>>>> Simon Lord
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>> Steven Dolg wrote:
> >>>>>>> Hi Simon,
> >>>>>>>
> >>>>>>> The 3828 FieldDescriptors indicate that the object graph your
> >>>>>>> (un)marshalling contains some more classes than the one you're
> >>>>>>> creating
> >>>>>>> the ClassDescriptorResolver for.
> >>>>>>> So the (Un)marshaller asks the ClassDescriptorResolver to find all
> >>>>>>> descriptors necessary for the whole object graph (not just the
> root
> >>>>>>> object).
> >>>>>>> This might lead to creating different ClassDescriptorResolvers
> (for
> >>>>>>> different root classes) that might contain almost identical
> >>>>>>> descriptors
> >>>>>>> (for all other objects in the object graph).
> >>>>>>>
> >>>>>>> It shouldn't be necessary to create a ClassDescriptorResolver for
> >> each
> >>>>>>> class individually so I'd suggest using only one resolver. (I'm
> not
> >>>>>>> entirely sure whether this is thread-safe or not)
> >>>>>>>
> >>>>>>> And do not forget to set the created ClassDescriptorResolver at
> the
> >>>>>>> (Un)marshaller... ;-)
> >>>>>>>        Unmarshaller unm = new Unmarshaller(...);
> >>>>>>>        unm.setResolver(cdr);
> >>>>>>>
> >>>>>>> Regards,
> >>>>>>> Steven
> >>>>>>>
> >>>>>>>
> >>>>>>> ----- Original Message ----- From: "Simon Lord"
> >>>>>> <[EMAIL PROTECTED]>
> >>>>>>> To: <[email protected]>
> >>>>>>> Sent: Wednesday, March 14, 2007 6:44 PM
> >>>>>>> Subject: [castor-user] [XML] XMLClassDescriptorResolver
> >>>>>>> XMLFieldDescriptorImpl cache possible memory leak
> >>>>>>>
> >>>>>>>
> >>>>>>>> Afternoon all,
> >>>>>>>>
> >>>>>>>> I've recently moved from using an old version of Castor (0.9.xxx)
> >> to
> >>>>>>>> the new stable 1.1. Mainly as i'd like to use the descriptor
> >> caching.
> >>>>>>>> However, after moving to castor 1.1 and creating an
> >>>>>>>> XMLClassDescriptorResolver as per the xml-best-practices webpage,
> >>>>>>>> running my application caused an out of memory expection
> >> (heapspace).
> >>>>>>>> So i ran the code under jProfiler and have seen symptoms of a
> >> memory
> >>>>>>>> leak (or symptoms of not using the resolver correctly ;-).
> >>>>>>>>
> >>>>>>>> It my understanding that when marshalling/unmarshalling, the
> >>>>>>>> XMLClassDescriptorResolver should be caching the descriptors for
> >> use
> >>>>>>>> in subsequent operations. Then on the subsequent operation
> (marshal
> >> /
> >>>>>>>> unmarshall) it shouldn't have to create those descriptors again
> >>>>>>>> (assumming the same class/xml complex type is being used).
> >>>>>>>>
> >>>>>>>> But what i've seen in jProfiler is that after one run of my code
> >>>>>>>> there
> >>>>>>>> have been 3828 XMLFieldDescriptorImpl objects created (triggering
> >>>>>>>> garbage collection a few times doesn't change that number either)
> >>>>>>>> then
> >>>>>>>> when i run it again (no restart, just second iteration) it
> finishes
> >>>>>>>> what it's doing and the count of XMLFieldDescriptorImpl objects
> is
> >>>>>>>> now
> >>>>>>>> 7725!
> >>>>>>>>
> >>>>>>>> It increases with each iteration, and after 10 iterations is
> 38901
> >>>>>>>> objects, taking up 3.4 megabytes in memory - after a while this
> >> gets
> >>>>>>>> so big it causes the memory exception.
> >>>>>>>>
> >>>>>>>> So it looks like it's created new XMLFieldDescriptorImpl for the
> >> same
> >>>>>>>> classes and xml complex types i used the first time around.
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> Has anyone else seen this behaviour before? Am i doing somthing
> >> wrong
> >>>>>>>> when creating / using the resolver?
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> Here's the code i use to contruct a resolver (sorry about the
> >>>>>>>> formatting):
> >>>>>>>>
> >>>>>>>> private XMLClassDescriptorResolver createResolver(Class clazz){
> >>>>>>>>
> >>>>>>>> XMLClassDescriptorResolver cdResolver =
> >>>>>>>>
> >>
> (XMLClassDescriptorResolver)ClassDescriptorResolverFactory.createClassDesc
> >>>>>> riptorResolver(BindingType.XML);
> >>>>>>>>
> >>
> cdResolver.setClassLoader(Thread.currentThread().getContextClassLoader());
> >>>>>>>> try {
> >>>>>>>>   cdResolver.loadClassDescriptors(clazz.getPackage().toString());
> >>>>>>>>   return cdResolver;
> >>>>>>>> } catch (ResolverException e) {
> >>>>>>>>   logger.warn(e.getMessage() +
> >> ":"+clazz.getPackage().toString(),e);
> >>>>>>>> }
> >>>>>>>> return null;
> >>>>>>>> }
> >>>>>>>>
> >>>>>>>> as you can see from the above code i create a resolver for each
> >> Class
> >>>>>>>> i marshal/unmarshall and store it for subsequent uses of the same
> >>>>>>>> operation (so i'm not creating a new resolver each time as it
> might
> >>>>>>>> appear)
> >>>>>>>>
> >>>>>>>> Thank you for your time
> >>>>>>>>
> >>>>>>>> Simon Lord
> >>>>>>>>
> >>>>>>>> -----------------------------------------------------------------
> --
> >> --
> >>>>>>>> To unsubscribe from this list please visit:
> >>>>>>>>
> >>>>>>>>    http://xircles.codehaus.org/manage_email
> >>>>>>> ------------------------------------------------------------------
> --
> >> -
> >>>>>>> To unsubscribe from this list please visit:
> >>>>>>>
> >>>>>>>    http://xircles.codehaus.org/manage_email
> >>>>>>>
> >>>>>> -------------------------------------------------------------------
> --
> >>>>>> To unsubscribe from this list please visit:
> >>>>>>
> >>>>>>     http://xircles.codehaus.org/manage_email
> >>>>>
> >>>>> --------------------------------------------------------------------
> -
> >>>>> To unsubscribe from this list please visit:
> >>>>>
> >>>>>     http://xircles.codehaus.org/manage_email
> >>>>>
> >>>>
> >>>> ---------------------------------------------------------------------
> >>>> To unsubscribe from this list please visit:
> >>>>
> >>>>    http://xircles.codehaus.org/manage_email
> >>>>
> >>> ---------------------------------------------------------------------
> >>> To unsubscribe from this list please visit:
> >>>
> >>>    http://xircles.codehaus.org/manage_email
> >>>
> >> ---------------------------------------------------------------------
> >> To unsubscribe from this list please visit:
> >>
> >>     http://xircles.codehaus.org/manage_email
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe from this list please visit:
> >
> >     http://xircles.codehaus.org/manage_email
> >
> 
> ---------------------------------------------------------------------
> To unsubscribe from this list please visit:
> 
>     http://xircles.codehaus.org/manage_email


---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply via email to