You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by Christophe Warland <ch...@s1.com> on 2003/03/10 22:47:09 UTC

Tiles excessive memory usage

At my company, we have been recently forced to patch Tiles to solve some
major memory problems where Tiles was eating a lot of memory for no apparent
reasons. We wish to share our findings with you. And we will be happy to
send our code change to Cedric if he wishes so. 
 
Here are some quick numbers about our J2EE runtime after complete bootup
(appserver and EAR file are up, deployed and ready to serve HTTP requests):
 - With original Tiles code: 79 MB of RAM is used
 - After our custom code change: 28 MB of RAM is used
 
Note that the Tiles version that we use is an old one (our source zip shows
09/10/2001). However, a quick analysis of the more recent Tiles source found
in Struts 1.1 RC1 shows that most the code where the defect lies is still in
there. But we haven't actually been able to confirm the problem at runtime
since our app is not compatible with the latest Struts and Tiles
development.
 
Here are a few excerpt of our internal analysis so that you can understand
the issue.
 
--
 
Our application does not actually make use of the Tiles template mechanism
but instead builds on top of Tiles' i18n concept to offer localized Web
pages based on an individual's language, country, personality and channel.
We make extensive use of Tiles Component definitions and inheritance in XML
files, and 667 out of the 668 definitions used by our app inherit from
another one.
 
With the help of a Java profiler, we showed that 64% of the 79 MB of memory
was used by HashMap entries created by Tiles.  This corresponds to 50.5 MB
of RAM. After close investigation, it turns out that the very useful Tiles'
component inheritance has been mis-implemented. 
 
Our application has only one definition that doesn't extend another one: the
root "pageDefinition", which contains common information such as
"pageCopyrightLink" for example. Other Component Definitions that extend
"pageDefinition", such as "disbursementCB", do not need to repeat this
information. When queried for the "pageCopyrightLink" value, the
"disbursementCB" component will delegate the processing to its parent
component, in this case "pageDefinition".
 
Unfortunately, this handy conceptual delegation is actually not implemented
in a similar way in the Tiles source code.
 
In our example, when the "disbursementCB" component is instantiated in
memory, the Tiles source code does not pass it a reference to the parent
"pageDefiniton" component. Instead, Tiles forces the new "disbursementCB"
component to make a deep copy of all values defined in its parent(s). This
means that, ultimately, our application ends up with 668 copies of the
"pageCopyrightLink" value in memory, instead of one. 
 
After modification of the Tiles source code so that true delegation is
actually happening in memory at runtime, new heap allocation statistics
showed that the problem with excessive usage of HashMap$Entry has been
completely solved. The most in-use object in the JVM is now of the type
"[C", a common and normal trend in typical Java applications.
 
The total amount of memory was also down to 28 MB. This is a pleasant 51 MB
gain over the previous result.

--
 
Finally, without being too demanding, we would appreciate if a patched
version of Tiles could be made available for for both the upcoming Struts
1.1 release and the current stabe Strust 1.0.2 one.
 
 
Best Regards,
 
 
Christophe Warland

Re: Tiles excessive memory usage

Posted by Cedric Dumoulin <ce...@apache.org>.
Hi Christophe,

    When you develop a software, you often need to choose between 
simplicity, CPU consumption and memory consumption
  In the case of the ComponentContext implementation, and the 
inheritance mechanism, I have chosen the simplicity and the CPU 
consumption.
  Furthermore,  while developping the ComponentContext (tile context) 
and the inheritance mechanism, I have tried to let the class 
ComponentContext independent from the ComponentDefinition class and its 
implementation.
  So, the implementation of ComponentContext create a new Hashmap 
initialized from the definition hashmap. Also, the definition 
inheritance is resolved in a way where each definition has its own 
hashmap referencing all the attributes visible by the definition. Note 
that the attributes themselves are shared between all definitions, they 
aren't copied.
  With this implementation, the access time to an attribute is constant. 
There is no need to check several hashmap. The drawback is the memory 
consumed. This is generally not really a problem on modern servers. The 
memory size is relatively constant because the hashmaps don't grow 
during the application life, they are initialized at startup only.

  Nevertheless, it is certainly possible to find a better compromise 
between the CPU memory consumption and the space memory consumption. For 
example, it is possible to avoid the map creation in the contexts when 
no "locale" attributes are set. Also, it is possible to control the 
definition map sizes, which is not modified once the definition 
inheritances are resolved.

  Maybe you can share with us your application used to do the benchmark 
(with all business stuff removed), and also the methodology used.
 
  Cedric

P.S.:   Je vois que avec le temps tu n'as rien perdu de ton esprit 
critique ;-).

Christophe Warland wrote:

> At my company, we have been recently forced to patch Tiles to solve 
> some major memory problems where Tiles was eating a lot of memory for 
> no apparent reasons. We wish to share our findings with you. And we 
> will be happy to send our code change to Cedric if he wishes so.
>  
> Here are some quick numbers about our J2EE runtime after complete 
> bootup (appserver and EAR file are up, deployed and ready to serve 
> HTTP requests):
>  - With original Tiles code: 79 MB of RAM is used
>  - After our custom code change: 28 MB of RAM is used
>  
> Note that the Tiles version that we use is an old one (our source zip 
> shows 09/10/2001). However, a quick analysis of the more recent Tiles 
> source found in Struts 1.1 RC1 shows that most the code where the 
> defect lies is still in there. But we haven't actually been able to 
> confirm the problem at runtime since our app is not compatible with 
> the latest Struts and Tiles development.
>  
> Here are a few excerpt of our internal analysis so that you can 
> understand the issue.
>  
> --
>  
> Our application does not actually make use of the Tiles template 
> mechanism but instead builds on top of Tiles' i18n concept to offer 
> localized Web pages based on an individual's language, country, 
> personality and channel. We make extensive use of Tiles Component 
> definitions and inheritance in XML files, and 667 out of the 668 
> definitions used by our app inherit from another one.
>  
> With the help of a Java profiler, we showed that 64% of the 79 MB of 
> memory was used by HashMap entries created by Tiles.  This corresponds 
> to 50.5 MB of RAM. After close investigation, it turns out that the 
> very useful Tiles' component inheritance has been mis-implemented.
>  
> Our application has only one definition that doesn't extend another 
> one: the root "pageDefinition", which contains common information such 
> as "pageCopyrightLink" for example. Other Component Definitions that 
> extend "pageDefinition", such as "disbursementCB", do not need to 
> repeat this information. When queried for the "pageCopyrightLink" 
> value, the "disbursementCB" component will delegate the processing to 
> its parent component, in this case "pageDefinition".
>  
> Unfortunately, this handy conceptual delegation is actually not 
> implemented in a similar way in the Tiles source code.
>  
> In our example, when the "disbursementCB" component is instantiated in 
> memory, the Tiles source code does not pass it a reference to the 
> parent "pageDefiniton" component. Instead, Tiles forces the new 
> "disbursementCB" component to make a deep copy of all values defined 
> in its parent(s). This means that, ultimately, our application ends up 
> with 668 copies of the "pageCopyrightLink" value in memory, instead of 
> one.
>  
> After modification of the Tiles source code so that true delegation is 
> actually happening in memory at runtime, new heap allocation 
> statistics showed that the problem with excessive usage of 
> HashMap$Entry has been completely solved. The most in-use object in 
> the JVM is now of the type "[C", a common and normal trend in typical 
> Java applications.
>  
> The total amount of memory was also down to 28 MB. This is a pleasant 
> 51 MB gain over the previous result.
> --
>  
> Finally, without being too demanding, we would appreciate if a patched 
> version of Tiles could be made available for for both the upcoming 
> Struts 1.1 release and the current stabe Strust 1.0.2 one.
>  
>  
> Best Regards,
>  
>  
> Christophe Warland



---------------------------------------------------------------------
To unsubscribe, e-mail: struts-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: struts-dev-help@jakarta.apache.org


Re: Tiles excessive memory usage

Posted by cw...@maine.rr.com.
Chris,

I'm just now getting to profiling our struts/tiles app and have always had some concern about the efficiency of the tiles.  Not that I'm a suspecting type of person but I just didn't have any information and that caused me to wonder.

Regardles when or if this fix gets placed in a release, would you be willing to offer sufficient code snippets that will give me enough understanding to implement your fix in my app?  I'm now getting deeper into tiles and getting a good feel for what's going on so this would be a perfect time for me before we enter client phase.  Also, I'd be willing to contribute this efficiency gain to the project(with your help or ok) if Cedric and the other powers agree this is something that should be done.

But in the meantime, could you supply me with some more detailed information and snippets.  This could potentially kill my project since performance is the major hot word amoung manager types these days where I work.  You can reply to cwilling@maine.rr.com with details that don't pertain to the developer's group if you like.

Thanks for posting this!!!!!!!

Chris Willingham
  ----- Original Message ----- 
  From: Christophe Warland 
  To: 'struts-dev@jakarta.apache.org' 
  Cc: 'cedric@apache.org' ; 'cedric.dumoulin@lifl.fr' 
  Sent: Monday, March 10, 2003 4:47 PM
  Subject: Tiles excessive memory usage


  At my company, we have been recently forced to patch Tiles to solve some major memory problems where Tiles was eating a lot of memory for no apparent reasons. We wish to share our findings with you. And we will be happy to send our code change to Cedric if he wishes so. 

  Here are some quick numbers about our J2EE runtime after complete bootup (appserver and EAR file are up, deployed and ready to serve HTTP requests):
   - With original Tiles code: 79 MB of RAM is used
   - After our custom code change: 28 MB of RAM is used

  Note that the Tiles version that we use is an old one (our source zip shows 09/10/2001). However, a quick analysis of the more recent Tiles source found in Struts 1.1 RC1 shows that most the code where the defect lies is still in there. But we haven't actually been able to confirm the problem at runtime since our app is not compatible with the latest Struts and Tiles development.

  Here are a few excerpt of our internal analysis so that you can understand the issue.

  --

  Our application does not actually make use of the Tiles template mechanism but instead builds on top of Tiles' i18n concept to offer localized Web pages based on an individual's language, country, personality and channel. We make extensive use of Tiles Component definitions and inheritance in XML files, and 667 out of the 668 definitions used by our app inherit from another one.

  With the help of a Java profiler, we showed that 64% of the 79 MB of memory was used by HashMap entries created by Tiles.  This corresponds to 50.5 MB of RAM. After close investigation, it turns out that the very useful Tiles' component inheritance has been mis-implemented. 

  Our application has only one definition that doesn't extend another one: the root "pageDefinition", which contains common information such as "pageCopyrightLink" for example. Other Component Definitions that extend "pageDefinition", such as "disbursementCB", do not need to repeat this information. When queried for the "pageCopyrightLink" value, the "disbursementCB" component will delegate the processing to its parent component, in this case "pageDefinition".

  Unfortunately, this handy conceptual delegation is actually not implemented in a similar way in the Tiles source code.

  In our example, when the "disbursementCB" component is instantiated in memory, the Tiles source code does not pass it a reference to the parent "pageDefiniton" component. Instead, Tiles forces the new "disbursementCB" component to make a deep copy of all values defined in its parent(s). This means that, ultimately, our application ends up with 668 copies of the "pageCopyrightLink" value in memory, instead of one. 

  After modification of the Tiles source code so that true delegation is actually happening in memory at runtime, new heap allocation statistics showed that the problem with excessive usage of HashMap$Entry has been completely solved. The most in-use object in the JVM is now of the type "[C", a common and normal trend in typical Java applications.

  The total amount of memory was also down to 28 MB. This is a pleasant 51 MB gain over the previous result.

  --

  Finally, without being too demanding, we would appreciate if a patched version of Tiles could be made available for for both the upcoming Struts 1.1 release and the current stabe Strust 1.0.2 one.


  Best Regards,


  Christophe Warland


------------------------------------------------------------------------------


  ---------------------------------------------------------------------
  To unsubscribe, e-mail: struts-dev-unsubscribe@jakarta.apache.org
  For additional commands, e-mail: struts-dev-help@jakarta.apache.org