Re: Optimising Variable to reduce instantiation overhead

Alex Twisleton-Wykeham-Fiennes <[email protected]> Sun, 12 Mar 2006 22:59:14 +0000
Newsgroups gmane.comp.java.webmacro.user
Message-ID <[email protected]>
On Sun 12 March 2006 21:20, Alex Twisleton-Wykeham-Fiennes wrote:
> On Sun 12 March 2006 21:14, Lane Sharman wrote:
> > alex,
> >
> > thanks for this improvement and catch. Are there any issues or concerns
> > you have with this proposed update?
>
> none that I can see - there is a very slight performance hit checking to
> see whether or not _vname has been initialised inside getVariableName()
> (along with the synchronized lock acquisition), but this is only ever
> invoked while constructing a PropertyException which has such a huge
> overhead from building the stack trace that it is irrelevant.
>
> The only potential problem is that there are some 3rd party extensions of
> Variable that aren't included in the standard ant build which might break
> by making _vname private, but these are easily refactored to use the method
> call instead.

I spoke to soon (sort of).

Being relatively new to ant, I didn't realise that you had to call clean 
before compile and so there were some broken subclasses of Variable that no 
longer compile due to the private _vname change.

I've refactored these classes, and attach them to this email.

The (properly) compiled tree still passes all the unit tests.

Alex

> Alex
>
> ps I posted some patches to the list to make Broker shutdown cleanly and
> ensure that webmacro applications unload cleanly when reloading under
> tomcat. I was about 20k over the list limit, and am in a blocking queue. 
> Do you know who is the list admin to let this through, or should I repost
> with the fixes chopped into smaller amounts?
>
> > Lane
> >
> > --- [email protected] wrote:
> >
> > From: Alex Twisleton-Wykeham-Fiennes <[email protected]>
> > To: [email protected]
> > Subject: [WebMacro-user] Optimising Variable to reduce instantiation
> > overhead Date: Sun, 12 Mar 2006 18:50:17 +0000
> >
> > All,
> >
> > more performance tweaks, this one to the org.webmacro.engine.Variable
> > class.
> >
> > performance sampling showed a large proportion of CPU time being
> > allocated to the makeName(Object[] names) class that is invoked in the
> > constructor to create the human-readable version of the Object[] that
> > stores the names, which is then stored in _vname.
> >
> > However, _vname is only ever used in situations when you generating
> > PropertyException Objects to provide sensible error messages, and for all
> > "correctly functioning" instances, this is completely redundant.
> >
> > What I've done is:-
> >
> > - disabled the call to makeName(names) in the constructor
> > - made the getVariableName() method check to see if _vname has been
> > initialised, and if not then build the name before returning it.  This is
> > now synchronized as it changes the state of the object.
> > - made all previous references to _vname in the Variable class invoke
> > getVariableName() rather than accessing the variable directly.
> > - made _vname private rather than protected thereby forcing sub-classes
> > to access it via getVariableName()
> >
> > The resulting class (attached) passes all the unit tests and completely
> > removes this overhead for all normal usage patterns.
> >
> > Alex
> >
> >
> >
> > -------------------------------------------------------
> > This SF.Net email is sponsored by xPML, a groundbreaking scripting
> > language that extends applications into web and mobile media. Attend the
> > live webcast and join the prime developer group breaking into this new
> > coding territory!
> > http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
> > _______________________________________________
> > Webmacro-user mailing list
> > [email protected]
> > https://lists.sourceforge.net/lists/listinfo/webmacro-user
>
> -------------------------------------------------------
> This SF.Net email is sponsored by xPML, a groundbreaking scripting language
> that extends applications into web and mobile media. Attend the live
> webcast and join the prime developer group breaking into this new coding
> territory!
> http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
> _______________________________________________
> Webmacro-user mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/webmacro-user
ConstantPropertyVariable.java (text/x-java, 2.3 KB)
/*
 * Copyright (C) 1998-2000 Semiotek Inc.  All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted under the terms of either of the following
 * Open Source licenses:
 *
 * The GNU General Public License, version 2, or any later version, as
 * published by the Free Software Foundation
 * (http://www.fsf.org/copyleft/gpl.html);
 *
 *  or
 *
 * The Semiotek Public License (http://webmacro.org/LICENSE.)
 *
 * This software is provided "as is", with NO WARRANTY, not even the
 * implied warranties of fitness to purpose, or merchantability. You
 * assume all risks and liabilities associated with its use.
 *
 * See www.webmacro.org for more information on the WebMacro project.
 */


package org.webmacro.engine;

import org.webmacro.Context;
import org.webmacro.PropertyException;


/**
 * Operate on bean properties of a compile-time constant
 * @author Brian Goetz
 * @since 1.1
 */
public class ConstantPropertyVariable extends Variable
{

    private Object value;

    /**
     * No special initialization
     */
    ConstantPropertyVariable (Object value, Object names[])
    {
        super(names);
        this.value = value;
    }

    /**
     * Look up my value in the corresponding Map, possibly using introspection,
     * and return it
     * @exception PropertyException If the property does not exist
     */
    public final Object getValue (Context context)
            throws PropertyException
    {
        if (value == null)
            throw new PropertyException.NullValueException(_names[0].toString());
        else
            return context.getBroker()
                    ._propertyOperators.getProperty(context, value, _names, 1);
    }

    /**
     * Look up my the value of this variable in the specified Map, possibly
     * using introspection, and set it to the supplied value.
     * @exception PropertyException If the property does not exist
     */
    public final void setValue (Context context, Object newValue)
            throws PropertyException
    {
        throw new PropertyException("Cannot set properties of a constant");
    }

    /**
     * Return a string representation naming the variable for
     * debugging purposes.
     */
    public final String toString ()
    {
        return "constant-property:" + getVariableName();
    }

}
FunctionVariable.java (text/x-java, 1.3 KB)
/*
 * FunctionVariable.java
 *
 * Created on March 21, 2003, 12:15 AM
 */

package org.webmacro.engine;

import org.webmacro.Context;
import org.webmacro.PropertyException;

/**
 *
 * @author  Keats
 */
public class FunctionVariable extends Variable
{
    final public static Object TYPE = new Object();

    /** Creates a new instance of FunctionVariable */
    public FunctionVariable (Object names[])
    {
        super(names);
    }

    /** The code to get the value represented by the variable from the
     * supplied context.
     *
     */
    public Object getValue (Context context) throws PropertyException
    {
       return context.getProperty(_names);
       //return context.getProperty(_names[0]);
    }

    /** The code to set the value represented by the variable in the
     * supplied context.
     *
     */
    public void setValue (Context c, Object v) throws PropertyException
    {
        throw new PropertyException("Cannot set the value of a function: " + getVariableName());
    }

    /**
     * Return the String name of the variable prefixed with a string
     * representing its type, in this case "function:".
     */
    public String toString ()
    {
        return "function:" + getVariableName();
    }

    public boolean isSimpleName ()
    {
        return false;
    }

}
GlobalVariable.java (text/x-java, 2.2 KB)
/*
 * Copyright (C) 1998-2000 Semiotek Inc.  All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted under the terms of either of the following
 * Open Source licenses:
 *
 * The GNU General Public License, version 2, or any later version, as
 * published by the Free Software Foundation
 * (http://www.fsf.org/copyleft/gpl.html);
 *
 *  or
 *
 * The Semiotek Public License (http://webmacro.org/LICENSE.)
 *
 * This software is provided "as is", with NO WARRANTY, not even the
 * implied warranties of fitness to purpose, or merchantability. You
 * assume all risks and liabilities associated with its use.
 *
 * See www.webmacro.org for more information on the WebMacro project.
 */


package org.webmacro.engine;

import org.webmacro.Context;
import org.webmacro.PropertyException;


/**
 * Operate on bean properties in a context
 */
final class GlobalVariable extends Variable
{

    /**
     * No special initialization
     */
    GlobalVariable (Object names[])
    {
        super(names);
    }

    /**
     * Look up my value in the corresponding Map, possibly using introspection,
     * and return it
     * @exception PropertyException If the property does not exist
     */
    public final Object getValue (Context context)
            throws PropertyException
    {
        return context.getProperty(_names);
    }

    /**
     * Look up my the value of this variable in the specified Map, possibly
     * using introspection, and set it to the supplied value.
     * @exception PropertyException If the property does not exist
     */
    public final void setValue (Context context, Object newValue)
            throws PropertyException
    {

        if (!context.set(_names, newValue))
        {
            throw new PropertyException("No method to set \"" + getVariableName() +
                    "\" to type " +
                    ((newValue == null) ? "null" : newValue.getClass().toString())
                    + " in supplied context (" + context.getClass() + ")");
        }
    }

    /**
     * Return a string representation naming the variable for
     * debugging purposes.
     */
    public final String toString ()
    {
        return "global:" + getVariableName();
    }

}
SimplePropertyVariable.java (text/x-java, 2.3 KB)
/*
 * Copyright (C) 1998-2000 Semiotek Inc.  All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted under the terms of either of the following
 * Open Source licenses:
 *
 * The GNU General Public License, version 2, or any later version, as
 * published by the Free Software Foundation
 * (http://www.fsf.org/copyleft/gpl.html);
 *
 *  or
 *
 * The Semiotek Public License (http://webmacro.org/LICENSE.)
 *
 * This software is provided "as is", with NO WARRANTY, not even the
 * implied warranties of fitness to purpose, or merchantability. You
 * assume all risks and liabilities associated with its use.
 *
 * See www.webmacro.org for more information on the WebMacro project.
 */


package org.webmacro.engine;

import org.webmacro.Context;
import org.webmacro.PropertyException;


/**
 * Operate on bean properties in a context; special case for simple variables
 * (only one name)
 */
final class SimplePropertyVariable extends Variable
{

    /**
     * No special initialization
     */
    SimplePropertyVariable (Object names[])
    {
        super(names);
    }

    /**
     * Look up my value in the corresponding Map, possibly using introspection,
     * and return it
     * @exception PropertyException If the property does not exist
     */
    public final Object getValue (Context context)
            throws PropertyException
    {
        return context.getProperty(_names[0]);
    }

    /**
     * Look up my the value of this variable in the specified Map, possibly
     * using introspection, and set it to the supplied value.
     * @exception PropertyException If the property does not exist
     */
    public final void setValue (Context context, Object newValue)
            throws PropertyException
    {
        if (!context.setProperty(_names[0], newValue))
        {
            throw new PropertyException("No method to set \"" + getVariableName() +
                    "\" to type " +
                    ((newValue == null) ? "null" : newValue.getClass().toString())
                    + " in supplied context (" + context.getClass() + ")");
        }
    }

    /**
     * Return a string representation naming the variable for
     * debugging purposes.
     */
    public final String toString ()
    {
        return "property:" + getVariableName();
    }

}
MacroPropertyVariable.java (text/x-java, 2.4 KB)
/*
 * Copyright (C) 1998-2000 Semiotek Inc.  All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted under the terms of either of the following
 * Open Source licenses:
 *
 * The GNU General Public License, version 2, or any later version, as
 * published by the Free Software Foundation
 * (http://www.fsf.org/copyleft/gpl.html);
 *
 *  or
 *
 * The Semiotek Public License (http://webmacro.org/LICENSE.)
 *
 * This software is provided "as is", with NO WARRANTY, not even the
 * implied warranties of fitness to purpose, or merchantability. You
 * assume all risks and liabilities associated with its use.
 *
 * See www.webmacro.org for more information on the WebMacro project.
 */


package org.webmacro.engine;

import org.webmacro.Context;
import org.webmacro.Macro;
import org.webmacro.PropertyException;


/**
 * Operate on bean properties of an existing macro; used when a Macro
 * is passed as an argument to a macro
 * @author Brian Goetz
 * @since 1.1
 */
public class MacroPropertyVariable extends Variable
{

    private Macro value;

    /**
     * No special initialization
     */
    MacroPropertyVariable (Macro value, Object names[])
    {
        super(names);
        this.value = value;
    }

    /**
     * Look up my value in the corresponding Map, possibly using introspection,
     * and return it
     * @exception PropertyException If the property does not exist
     */
    public final Object getValue (Context context)
            throws PropertyException
    {
        Object v = value.evaluate(context);
        if (v == null)
            throw new PropertyException.NullValueException(_names[0].toString());
        else
            return context.getBroker()
                    ._propertyOperators.getProperty(context, v, _names, 1);
    }

    /**
     * Look up my the value of this variable in the specified Map, possibly
     * using introspection, and set it to the supplied value.
     * @exception PropertyException If the property does not exist
     */
    public final void setValue (Context context, Object newValue)
            throws PropertyException
    {
        throw new PropertyException("Cannot set properties of a constant");
    }

    /**
     * Return a string representation naming the variable for
     * debugging purposes.
     */
    public final String toString ()
    {
        return "macro-property:" + getVariableName();
    }

}
PropertyVariable.java (text/x-java, 2.2 KB)
/*
 * Copyright (C) 1998-2000 Semiotek Inc.  All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted under the terms of either of the following
 * Open Source licenses:
 *
 * The GNU General Public License, version 2, or any later version, as
 * published by the Free Software Foundation
 * (http://www.fsf.org/copyleft/gpl.html);
 *
 *  or
 *
 * The Semiotek Public License (http://webmacro.org/LICENSE.)
 *
 * This software is provided "as is", with NO WARRANTY, not even the
 * implied warranties of fitness to purpose, or merchantability. You
 * assume all risks and liabilities associated with its use.
 *
 * See www.webmacro.org for more information on the WebMacro project.
 */


package org.webmacro.engine;

import org.webmacro.Context;
import org.webmacro.PropertyException;


/**
 * Operate on bean properties in a context
 */
final class PropertyVariable extends Variable
{

    /**
     * No special initialization
     */
    PropertyVariable (Object names[])
    {
        super(names);
    }

    /**
     * Look up my value in the corresponding Map, possibly using introspection,
     * and return it
     * @exception PropertyException If the property does not exist
     */
    public final Object getValue (Context context)
            throws PropertyException
    {
        return context.getProperty(_names);
    }

    /**
     * Look up my the value of this variable in the specified Map, possibly
     * using introspection, and set it to the supplied value.
     * @exception PropertyException If the property does not exist
     */
    public final void setValue (Context context, Object newValue)
            throws PropertyException
    {
        if (!context.setProperty(_names, newValue))
        {
            throw new PropertyException("No method to set \"" + getVariableName() +
                    "\" to type " +
                    ((newValue == null) ? "null" : newValue.getClass().toString())
                    + " in supplied context (" + context.getClass() + ")");
        }
    }

    /**
     * Return a string representation naming the variable for
     * debugging purposes.
     */
    public final String toString ()
    {
        return "property:" + getVariableName();
    }

}