Unnecessary memory allocation in MethodMetaData & MethodHash
fl_ Aug 15, 2008 8:03 PMHi,
Last time I noticed that our application that we are working on is used to allocating around 500MB per second. As it can be expected GC is getting crazy ;)
To accomplish one request our application perform around 10-20 remote invocations.
Load under which application allocate 500M/s is about 100 request per second.
I just finished small test. The goal of test was check how much memory is allocated per EJB invocation and find a way to optimize it.
So testing environment was prepared:
Client ---> FacadeBean ----> Worker MDB ------ (X times) -----> TargetBean
So Client connect to Facade which was entry point. Facade put one message describing testcase into queue (home many invocation, local or remote interface should be used). Worker MDB perform testcase by invoking TargetBean in loop.
Testcase:
500 000 invocations to TargetBean was performed. Each invocation use null values as parameters to reduce synchronization.
I found out that one of hot spots of memory allocation was method:
java.lang.reflect.Method.toString()
which was mostly invoked by following two classes:
org.jboss.aop.metadata.MethodMetaData.getMethodMetaData(java.lang.reflect.Method, Object, Object)
org.jboss.aop.util.MethodHashing.calculateHash(java.lang.reflect.Method)
So I introduced small cache for these strings and modified above two classes to use this cache.
Results:
Remote interface: time[ms] allocatedMemory[GB] GCscavenge Baseline: 49559 37.67 7878 Optimized: 36910 23.38 5339 Local interface: time[ms] allocatedMemory[GB] GCscavenge Baseline: 18705 18.04 3856 Optimized: 5267 1.41 449
Time - is the time needed to accomplish all invocations
allocatedMemory - is amount of memory that was allocated to accomplish all invocation. It is not exactly value, it should be treated as estimation, it was measured by -Xloggc
GCscavenge - number of scavenge GC events, measured by -Xloggc
Do you think it can be point for optimization?
3 times faster for local invocations and ~25% faster for remote.
Of course my implementation was extremely simple:
1) concurrent access wasn't taken under consideration - ConcurrentHashMap was used but only one thread thread were used in test scenario so
2) cache maintenance wasn't taken under consideration - is it can cause memory leak if applications will be redeployed often ?
Let me know if you want more details about results.
BR
ps. notice that performance improvement depends on method signature ... so ... to achieve better performance we should use shorter package names ;)