Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

AspectJRuntimeSpeed

Revision as of 21:43, 12 October 2009 by Simoneg.apache.org (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

This page gives tips for increasing the speed of your program when using AspectJ. If you need to speed up your build time, see tips for improving build performances

The performance of functionalities added to your program using aspects should be roughly the same as if those functionalities were coded directly in Java. If this is not the case, then maybe you hit a bug a should report it.

Anyway, it's still possible that the performance problem is caused by your specific use of AspectJ runtime functionalities, like the thisJoinPoint variable or runtime checking pointcuts.

thisJoinPoint

thisJoinPoint is a variable offered by AspectJ to extract context informations. Anyway, using this special variable has its cost.

Use the static part whenever possible

thisJoinPointStaticPart is another special variable offered by AspectJ. It contains all the informations about the current pointcut that can be determined statically. So, it does need to be instantiated for each invocation but only once in the JVM lifetime, which is a great time saver.

If context informations you need can be found in thisJoinPointStaticPart then use it instead of thisJoinPoint.

Guard thisJoinPoint creation

A common anti-performance-pattern is the following :

after() : execution(......) {

 if (logEnabled) {
   // do some logging
 }

}

thisJoinPoint if created when an advice using it is first executed. So, in this case, if logEnabled is false, thisJoinPoint is created every time even if it is useless. You can put an if() pointcut to avoid wasting this time, instead of an if as the first instruction of your advice.

Use context bindings

AspectJ offers a number of context binding pointcuts. Some of these are this(), target(), args(). Using these pointcuts instead of raw access to thisJoinPoint makes your code more readable and can help inprove runtime performances.

Runtime checking pointcuts

Some AspectJ pointcuts perform runtime checks. These are :

  • if()
  • this(Type)
  • target(Type)


There is nothing wrong with this pointcuts, but if you consider what happens when weaving the following pointcut :

after(String stmt) : execution(void *.set*(String)) && args(stmt) && if(stmt.length() > 0) {

 // advice body

}

every setter taking a String argument will be weaved with :

 public void setSomething(String arg) {
   if (arg.length() > 0) {
     // call advice
   }
   // rest of setter code
 }

If this matches too many places, it can cause runtime performance problems.

What you cont need to do or cannot do

ITD performances

ITD methods (Inter Type Declaration methods) are implemented as a double method call. In fact, a "proxy" method is weaved into the target type, and that method then calls the real ITD body.

This has a minimal performance impact, largely compensated by the smaller overhead if compared to inserting the ITD method body inside all the target classes. Moreover, this impact should disappear when JIT comes into play. (1)


Avoiding parameters creation

You cannot use AspectJ to avoid the overhead of creating parameters passed to a method call in your existing code (2). A common example of this is weaving calls to a log system so that they are not executed when the proper log level is not activated.

Consider for example :

 logger.debug("A " + "string " + "containing " + myobject.toString() + " overhead");

You may be tempted to write :

 void around() : call(void Logger.debug(String)) {
   if (debugLogging) {
     proceed(.....);
   } else {
     return;
   }
 }

This code will avoid calling the logger.debug method, but the argument string will still be created. This is because, if seen from a bytecode point of view, the weaved code reads more or less like this :

String param = "A " + "string " + "containing " + myobject.toString() + " overhead"; if (debugLogging) {

 logger.debug(param);

}

So, the parameters are always created by the JVM before the actual call.


References

(1) : Andrew Clement "RE: ITD Implementation & Performance" on aspectj-users mailing list.

(2) : Andrew Clement "RE: Logger guard with aspectj" on aspectj-users mailing list.

Back to the top