jastrachan | 13 May 19:18 2004
Picon

Re: [groovy-dev] Optimizing Scripts (just an Idea)

Great idea Thomas.

The main reason that Scripts have used a binding for all their 
variables, up to now, is that folks executing arbitrary expressions, 
command line tools, BSF integration and the like are used to working 
like this. i.e. you setup some state outside of the script, run the 
script, then look at the state again later.

I guess there should be a way to specify that you don't want scripts to 
use bindings at all; or that bindings are used for input only - that 
there's no need to output values. Though I've always thought if users 
wanted this kind of optimisation, why not just use a class with regular 
methods?  Or quietly wrap the script in a class before you compile it 
:)

One other thought was; if you're using a class (or at least disabling 
the 'binding' feature) then you can actually use local variables, 
rather than fields in the script - which can be more efficient, use a 
little less ram and maybe give the GC a hint to release resources 
eariler.

Plus you'll have problems if you reuse the same variable name inside 
the script in different scopes)

e.g.

for (x in 0..10) {
     Integer z  = x * 123
}

for (y in 30..55) {
    String z = "hello"
}

Though you could automagically use different field names under the 
covers.

Maybe we need some kind of flag in the CompilerConfig or GroovyShell or 
whatnot to allow enable/disable of binding value exports? We could 
always disable exporting of variables by default but provide the user 
with a way to export values to the caller.

e.g.

x = 123 // local variable
binding.y = 456 // output this to the binding I was passed

On 13 May 2004, at 15:28, Thomas Heller wrote:
> Hey guys,
>
> I know its not the time to optimize yet but unfortunatly I didn't have 
> the pleasure to play with bytecode generation yet so I can't test this 
> for myself but maybe you guys can help. I'd really appreciate some 
> feedback here.
>
> I've done alot of groovy scripts to this day and one webapp is going 
> to go live pretty soon which is exclusivly using groovy on the 
> presentation side. Well, the results so far are quite good (better 
> than jsp2) but well if theres room to optimize I'm up to it. (and its 
> fun to think about).
>
> Here's what I have come up with so far: Its untested and just an idea!
>
> The major problem in Scripts today is that variables are slow (meaning 
> it requires a hashmap lookup each time). As said I don't know about 
> bytecode so I'll do this in plain java with a very simple example 
> (only get/set)
>
> script:
>
> x = 3;
> println(x);
>
> Right now this results (basically) I think, correct me if the bytecode 
> does something different:
>
> public class Test extends Script {
> 	public Object run() {
> 		this.setProperty("x", 3); //<- replace 3 with correct groovy type
> 		println(this.getProperty("x"));
> 	}
> }
>
> the slow part beeing the hashmap backend:
>
> binding.setVariable("x", 3);
> binding.getVariable("x");
>
>
> I've seen in the parser that it knows when its in a script body so 
> what I thought was that it should collect every used variable and 
> declare them just like this:
>
> public class Test extends Script {
>    private final ScriptVariable x;
>
>    public Test(Binding binding) {
>       this.x = binding.registerVariable("x");
>    }
>
>    public Object run() {
>       this.x.set(3); // <- again use groovy type
>       println(this.x.get());
>    }
> }
>
> With:
>
> public class DefaultScriptVariable implements ScriptVariable { // 
> Seriablizable/Cloneable if needed
>     private final String name;
>     private Object value;
>
>     public ScriptVariable(String name, Object value) {
>         this.name = name;
>         this.value = value;
>     }
>
>     public Object get() {
>         return value;
>     }
>
>     public Object set(Object value) {
>        return this.value = value;
>     }
> }
>
> or LazyScriptVariable is also doable but thats up to the binding.   
> Aka we could use a different Strategy if we want to save the Map 
> lookup at the beginning (registerVariable). Some sort of WeakReference 
> should be possible too?
>
> Binding in turn would always be a Map<String, ScriptVariable> but 
> could offer the usual map methods for simplicity. 
> binding.registerVariable would be something like:
>
> public ScriptVariable registerVariable(String name) {
>    ScriptVariable var = (ScriptVariable )map.get(name);
>    if (var == null) {
>       var = new ScriptVariable(name, null); // defaults to null
>       map.put(name, var);
>    }
>
>    return var;
> }
>
> or for lazy
>
> public ScriptVariable registerVariable(String name) {
> 	return new LazyScriptVariable(name, this);
> }
>
> If you want to pass variables from the outside you do it via binding 
> just like you used to. binding.setVariable("x", 3) would work with 
> ScriptVariable internally but never expose it to the outside (only via 
> registerVariable)
>
> One change this also incorporates is the immutable Binding on the 
> Script instance which I think is a good idea honestly. I don't think 
> its worth to pool Script instances and use setBinding(binding), run() 
> multiple times. This needs to be tested tho, but the cost of the pool 
> should be higher than new Script(binding).run();
>
> Well, I think a class member that does not require a map lookup 
> (everytime) is faster than the way its done now but unfornutatly I 
> don't have any real tests to prove what I'm saying. If someone could 
> help me out with the bytecode (or _how_ exactly setProperty("x", 3) 
> looks, the 3 thing) I'd really like to run some tests against this.
>
> If you think this is non-sense please tell me why I maybe heading in 
> the wrong direction here. ;)
>
> /thomas
>
> PS: perhaps its possible to save the type or some other hints for 
> groovy too. Perhaps it could save some casts.
> _______________________________________________
> groovy-dev mailing list
> groovy-dev@...
> http://lists.codehaus.org/mailman/listinfo/groovy-dev
>
>

James
-------
http://radio.weblogs.com/0112098/

Gmane