Thursday, April 22, 2004

Java; POI Optimization - Speeding up the RecordFactory class.

This optimization needs two posts. This post presents a class that maps short values to a Constructor object. The RecordFactory class maps the short id value in the Excel file to a Java class. In the current version of POI, that relationship is kept, quite logically, in a Map object. However, using a Map object required that the short value be converted into a Short object quite frequently. This conversion is inefficient and, if some specially coding is done, unneeded. Note that the following class, shortToConstructorCache, is derivative of my earlier shortShortCache class.

 * Cache a mapping from a short value to a Constructor object.
 * This class is designed to optimize the RecordFactory.createRecord()
 * method. It might be useful in other contexts, but I did not check.
public class shortToConstructorCache {

     * The number of entries in the cache.
    protected int       distinct;

     * The cached short values.
    private short       table[];

     * The cached constructor methods
    private Constructor values[];

     * RecordFactory uses a statically created array of
     * classes to initialize the cache and the entries
     * in the cache are never changed nor added to.  
    public shortToConstructorCache(Class[] records) {
    	this.table = new short[records.length];
    	this.values = new Constructor[records.length];

        Constructor constructor;

        for (int i = 0; i < records.length; i++) {
            Class record = null;
            short sid = 0;

            record = records[i];
            try {
                sid = record.getField("sid").getShort(null);
                constructor = record.getConstructor(new Class[] {short.class, short.class, byte[].class});
            } catch (Exception illegalArgumentException) {
                throw new RecordFormatException("Unable to determine record types");

            if (constructor == null) {
                throw new RecordFormatException("Unable to get constructor for sid [" + sid + "].");
            } else {
                this.table[this.distinct] = sid;
                this.values[this.distinct] = constructor;

    /** Gets the Constructor object related to a given
     * key.
    public Constructor get(short key) {
        Constructor rv = null;
        	for (int i = 0; i < this.distinct; i++) {
        	    if (this.table[i] == key) {
        	        rv = this.values[i];
        return rv;
    /** Returns the number of entries in the cache. */
    public int size() {
        return this.distinct;
    /** We're breaking encapsulation but some code in RecordFactory
     * wants the information and I want to change RecordFactory as
     * little as possible.
    public short[] getTable() {
        return this.table;

Post a Comment