Saturday, January 07, 2012

Stackless Exceptions for Improved Performance

One of the reasons for standard exceptions being slow is that they have to fill in the execution stack trace for the current thread. Although, this is useful for debugging, in most cases you don't really care about the stack trace. What you care about is that an exception of a certain type was thrown and what the error message was. For example, a java.io.FileNotFoundException was thrown with message config.xml (The system cannot find the file specified)".

Stackless Exceptions are exceptions without any associated stack information. They are faster to create than normal exceptions because they don't record information about the current state of the stack frames for the current thread.

The class below is an example of a stackless exception. The fillInStackTrace method has been overridden so that it doesn't do anything and simply returns the current instance.

/**
 * An exception which does not fill in a stack trace
 * for performance reasons.
 */
@SuppressWarnings("serial")
public class StacklessException extends Exception {

    /**
     * Constructs a new stackless exception
     * with the specified detail message.
     *
     * @param message the detail message.
     * @see java.lang.Exception#Exception(String)
     */
    public StacklessException(String message) {
        super(message);
    }

    /**
     * Does not fill in the stack trace for this exception
     * for performance reasons.
     *
     * @return this instance
     * @see java.lang.Throwable#fillInStackTrace()
     */
    @Override
    public Throwable fillInStackTrace() {
        return this;
    }
}
I measured performance by comparing the time taken to create a million StacklessException and Exception objects. I found that the creation of stackless exceptions is nearly 40 times faster than normal exceptions.

You can then create more specific exception types which subclass StacklessException. For example:

public class PersonNotFoundException extends StacklessException {
    public PersonNotFoundException(String message) {
        super(message);
    }
}
As an aside, note that the JVM omits stack traces if an exception is thrown very frequently. This optimisation is enabled by default and can be disabled using the JVM option -XX:-OmitStackTraceInFastThrow.

No comments:

Post a Comment