Kabir Khan [
http://community.jboss.org/people/kabir.khan%40jboss.com] replied to the
discussion
"JBoss Reflect Performance Javassist vs Introspection"
To view the discussion, visit:
http://community.jboss.org/message/537944#537944
--------------------------------------------------------------
I've attached the classes I put together for measuring this. I think I included
everything needed to make them run, let me know if you have any problems. I used asm 3.2.
I haven't looked too deeply into why the performance is different, but I think it is
due to how Bytecode and ConstPool make use of ByteVector and LongVector while their asm
counterparts seem to modify the byte array directly. Javassist, on the other hand, needs
to convert those to create the byte arrays. I have not done any measurements of this, but
I guess with things the way they are that once the class bytes are parsed that javassist
would be faster for calling things like getMethod() etc.?
The reason why this becomes important is that this is something that gets called huge
numbers of times. However, there are other problems with this approach of generating
accessors with bytecode, which means I am not 100% sure we should go with this approach.
This is that we end up with:
* having to load a lot of extra classes which takes a lot of time and fills up
PermGenSpace
* a lot of instances (although the number of instances probably holds true when we just
use java.lang.reflect.Method instead)
My idea of creating bigger accessors isn't that viable either. If you have a class
that has 300 members, but only 30 of those are used with the original method you end up
with 30 small classes. With the "bigger accessor" idea, you end up with only one
class, but with the code to access all 300 members, so that is a waste of memory.
If an accessor is called a lot of times it makes sense to generate a class for it.
However, if it is called only a few times, then generating and loading a class for it will
be slower due to having to load the class.
The main use-cases I know of are:
* Configuring the properties of the MC beans. For most bean classes I think each property
is only installed once. However, in other cases, e.g. the properties of the beans for the
AOP metadata + the beans installed by EJB 3 probably get accessed a lot of times, so for
these it would make sense to generate classes.
* JBossXB parsing. It is used for parsing the schema, which only happens once, but when
parsing the xml files, I think the accessors are used a lot.
I think we need some kind of differentiator, so that for accessors that only get called a
few times we just go with norrnal reflection, but for heavily used accessors we go with
generating the classes. I'll try to come up with some numbers for how many times we
need to access the member for generating the class to be the cheapest option.
The question is what differentiator to use? A few ideas:
* Keep a counter in Javassist[Method/Field/Constructor]Info and once it has been called
several times switch to the generated class. The problem with this is, what if this
counter kicks in and we end up generating the class and then we don't have enough
subsequent accesses to reap the performance benefits, i.e. in this case it would slow it
down.
* Use some annotation to say that for a particular class we should always use generated
members. If this annotation comes from MC BeanMetaData it could be put into the TypeInfo
attachments.
I will build some statistics into JavassistConstructorInfo.newInstance(),
JavassistMethodInfo.invoke() etc. so it is possible to get a report of the type of
accessor used and the number of calls to help with being able to tune it using annotations
unless somebody has some different ideas.
--------------------------------------------------------------
Reply to this message by going to Community
[
http://community.jboss.org/message/537944#537944]
Start a new discussion in JBoss Microcontainer Development at Community
[
http://community.jboss.org/choose-container!input.jspa?contentType=1&...]