Groovy performance: what to do

View: New views
20 Messages — Rating Filter:   Alert me  
< Prev | 1 - 2 - 3 - 4 | Next >

Re: Groovy performance: what to do

by Martin C. Martin :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Tom,

Tom Nichols wrote:

> On Thu, Feb 21, 2008 at 4:35 AM, Guillaume Laforge <glaforge@...> wrote:
>>  It's not a problem of annotation vs keyword.
>>  It's the concept which is not the right thing to do.
>>  It's about making the whole Groovy language faster in all possible
>>  scenarios, not just through one hack to speed-up one or two methods,
>>  which will never be as fast as Java anyway.
>>  Let's make everything at least as fast as this hack.
>
> I think the "pro static annotation" people are basing their argument
> on the assumption that "pure" dynamic Groovy will never be able to
> attain the same performance of a non-dynamic-annotated variant.  If
> re-architecting Groovy's MOP will allow it to attain ~half of Java's
> speed, then fine, that's great, go there.

That's a good summary.  This thread started because Alex needed 4
attempts to rewrite the call site optimization to "avoid some
very tricky bugs with EMC and categories on multi-threading."  I suspect
that getting within a factor of 2 of Java's speed is very tricky while
still maintaining full dynamics.  Guillaume is talking about being the
fastest *dynamic* language on the JVM, being faster than Jython or
JRuby, and being within a factor of 10 of Java.

If it turns out there's a MOP that can be practically implemented that
gets within a factor of 2 of Java's speed, then there's no need for the
annotation/keyword.  But these things are often very very hard to get
right, or even impossible beyond the simplest cases.

> But I agree with Martin's argument that most people will ignore such
> an annotation until it comes time to do performance tuning anyway.
> Then sprinkle a few annotations in the performance bottlenecks, versus
> (the current solution) breaking some code out into Java classes.  Like
> I said, I would prefer the former, but if it truly won't be necessary
> after "Groovy 2.0" then it is a moot point.
>
> As annotations go, aren't they modular in the sense that you can add
> hooks into places without them actually being hard-coded into the
> compiler?  Maybe the groovy compiler doesn't support it now, but
> doesn't the Java (5 or 6) compiler?  Would it be possible to allow
> this compile-time annotation without "invading" core Groovy?

The compiler would need to change the code that's generated, in a way
that would change the semantics.  Of course, the idea is to use it where
the new semantics would be the same as the old semantics, but in Alex's
proposal it's up to the programmer to ensure that.

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email



Re: Groovy performance: what to do

by Pascal DeMilly-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

The problem with this is that java calling back Groovy generated classes
doesn't follow exactly the same execution path.

Guillaume Laforge wrote:

> The problem with this approach is that it'd be like focusing on the
> short term and not the longer term, despite the facts that:
> - it's so easy to use Java when really needed
> - it wouldn't be as fast as raw Java anyway
> - the code base would become littered with this annotation all over
> the place for no sane reason (remember the ugly @Property all over the
> place?)
> - having such quick wins in place wouldn't force us to think about a
> better underlying architecture, preventing Groovy from really scaling
> upward any day soon
>
> And I could certainly find other very good valid reasons.
>
> On Tue, Feb 19, 2008 at 3:26 PM, Tom Nichols <tmnichols@...> wrote:
>  
>> I like Alex's ideas.  Yes, it does limit what Groovy can do in certain
>>  siturations but
>>
>>  1. it's optional, so the developer does this of his/her own volition,
>>  not due to any language constraints.
>>  2.  How invasive is this change?  Is it really just a new annotation
>>  and some hooks in the compiler?  Or does it require changes to the
>>  runtime too?
>>
>>  To me this seems like just another tool.  It doesn't force Groovy in
>>  any direction.  It just gives the developer more options.  They can
>>  use it, or choose not to.  Yes, it would cause some things to not work
>>  (i.e. libs that rely on runtime-dynamic stuff like GORM) but it would
>>  allow other situations to use Groovy's great syntax and some (most?)
>>  of its features without resorting to Java.  Why not give the developer
>>  this tool (with the caveat that it is not a "magic speed-up button")
>>  and allow them to use it or not?
>>
>>  I think that if we can suddenly have ~90% of Java's speed with such a
>>  (seemingly) simple change, it would be well worth it.  I would
>>  definitely prefer to write "static, annotated Groovy" versus Java.
>>
>>  -Tom
>>
>>
>>
>>  ---------------------------------------------------------------------
>>  To unsubscribe from this list, please visit:
>>
>>     http://xircles.codehaus.org/manage_email
>>
>>
>>
>>    
>
>
>
>  


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email



Parent Message unknown Re: Groovy performance: what to do

by Gavin Grover :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

----- Original Message ----From: Guillaume Laforge

> On Thu, Feb 21, 2008 at 3:34 PM, Smith, Jason, CTR, OASD(HA)/TMA
> wrote:
> > Um, maybe we could end this whole debate by making the GroovyClassloader
> >  compile *.java files on the fly, the way it works with *.groovy files?
> >  That way, we could treat Java like script.  No compile step.
> >
> >  It would be pretty trivial to do this, I think.
>
> The joint Groovy / Java compiler just does it in Groovy 1.5.
> Seamlessly mixing both languages is a real no-brainer.

Perhaps even mixing Groovy classes and Java classes in the same source file.

Cheers, Gavin Grover
gvgrover@...
gavingrover.blogspot.com




      ____________________________________________________________________________________
Looking for last minute shopping deals?  
Find them fast with Yahoo! Search.  http://tools.search.yahoo.com/newsearch/category.php?category=shopping

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email



Re: Groovy performance: what to do

by Jochen Theodorou :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi all,

I want to summarize this discussion a bit from my perspective.

1.) current Groovy is not fast enough
2.) some want to replace Java with Groovy

So th real problem as I see it is, that people want 1+2, because if you
would replace some Groovy code with Java, then it would be fast enough
in most cases. But Groovy was not thought as a replacement of Java. It
was thought as a friend. I mean... would we have added generic
signatures to Groovy if Groovy was thought to replace Java? No, we would
not, because Groovy has no benefit from it. Same for Enums for
example... we might have done also another form of annotations and there
are a lot of other small things that we would have done different.
Groovy is designed to work side-by-side with Java.

then there are some things about such a "fast mode" we should shed some
light on.... Let me make 3 categories of typing:

1.) dynamic typing:

only the runtime type is used

2.) static typing:

only the compile time type is used, each type must be declared. In some
systems the compiler can guess the type well enough to let you omit the
type information

3.) mixed typing:

if the static type is not known, the dynamic type will be used.


Groovy has atm dynamic typing. Any change with a fast mode goals a more
or less static system, which is a major change for such a language.
There is either version 2, which will mean you can not mix dynamic typed
parts and static typed parts in the same area and there is version 3
which allows that, but will also give not many hints when it will do
static and when it will do dynamic typing.

In my eyes version 3 has many pitfalls, because the way a method call is
made will be changed by this. And I do not mean the MOP, I mean the
method that will be selected:

def foo (String s) {1}
def foo (Object o) {2}

String a = "test"
Object b = a
def    c = a
def    d = b

// with dynamic typing (version 1)
assert foo(a) == 1
assert foo(b) == 1
assert foo(c) == 1
assert foo(d) == 1

// with java style static typing  (version 2)
// def is like Object
assert foo(a) == 1
assert foo(b) == 2
assert foo(c) == 2
assert foo(d) == 2

// with static typing and inference (version 2)
// def is infered
assert foo(a) == 1
assert foo(b) == 2
assert foo(c) == 1
assert foo(d) == 2

As you can see, the methods that are called differ very much... and I
did not even mention our multimethods yet.

Some argue, that they would like to use Groovy, because it has a better
syntax... for example with closures. Let us forget a moment about the
GDK methods. Let us first look at a usage of Closures:

def foo(closure) {
   closure()
}
foo { println 1 }

That is kind of simple. In this version foo does not ensure that
"closure" is really a Closure, so "closure()" might fail later... but
that can be easily fixed by:

def foo(Closure closure) {
   closure()
}
foo { println 1 }

simple and clean for dynamic typing. The essential question  for static
typing is: How many parameters has my closure and how are they typed? If
  we look at the Closure class, then we will see that Closure supports
any number of arguments. That basically means, that any of these calls
is valid and some will fail at runtime:

closure()                //ok
closure(null)            //ok
closure(null,null)       //fails at runtime
closure(null,null,null)  //fails at runtime

"{ println 1 }" is a closure that takes 1 or 0 arguments, so the first
two calls are ok, the last two are not. And that's not all... the
Closure code is in a method doCall implemented, which is not visible in
the class Closure.What I want to say, that for Groovy closures, the
Closure class contains not enough information to let the compiler
produce a direct call and to ensure the call is valid as much as it
concerns the types and number of arguments.

That will mean, even if the compiler knows that a closure has two
arguments and which types they are and knows that the method will make
use of them and that the types are fitting... we can still not make a
direct call. And that will mean that a call on a closure will have the
speed of a dynamic method call... This can be solved by an annotation,
but the code will change:

@ClosureSignature(}
def foo(Closure closure) {
   closure()
}

foo { println 1 }

or another example:

@ClosureSignature([Object]}
@ClosureSignature([Object,Object]}
def foo(Map m, Closure cl) {
   if (cl.maximumParameters == 2) {
     m.each {key,value -> cl(key,value)}
   } else if (cl.maximumParameters == 1) {
     m.each {entry -> cl (entry)}
   }
}
def map = [:]
foo (map) {println it}
foo (map) {a,b-> println(a); println(b)}

so the validation problem can be solved, but a direct call to the
correct method is still impossible this way. If we add a method to
Closure which we can call directly, then we would have to add a method
that takes any number of arguments, which means that we will need to
pack and unpack the arguments in a Object[] for each call... Well,
that's probably better than the current situation, but a closure will
still be much slower than a direct method call. So looking at the
performance only means that you should not use Closure at all then.

Well, we could also define a Set of helper interfaces, which means we
will have to throw away optional arguments and which also means, that we
now need two methods:

def foo(Map m, <O,O> cl) {
   m.each {key,value -> cl(key,value)}
}

def foo(Map m, <O> cl) {
   m.each {entry -> cl (entry)}
}
def map = [:]
foo (map) {println it}  // closure implements <O>
foo (map) {a,b-> println(a); println(b)} // closure implements <O,O>

I guess that is the way the Closure proposals will take.. but it means
to either loose optional arguments in whole Groovy, or to double
implement/work with redirects. but it is unsure if our solution would
conflict with the solution Java might get.

And may I ask what is left of Groovy if we use no closures? Is there
enough to have it still as a replacement for Java? Will you still want
to replace Java with Groovy in the cases where you need no MOP, no
Builder, no Grails and other things?

The way we want to go is to find a fast method selection process, where
the selection will be cached at the place where the method call will be
done (call site cache) and in later calls we will need only a
verification step here, which can be much faster than the normal method
selection and which probably can be inlined by the JIT together with the
method call itself. This will mean that.

I wrote the things above to show why we talk about a language in a
language here. I mean if not even the same methods are called, if many
features are no longer available.. That's really another language

bye blackdrag

--
Jochen "blackdrag" Theodorou
The Groovy Project Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/
http://www.g2one.com/

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email



Re: Groovy performance: what to do

by Tom Nichols :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Fri, Feb 22, 2008 at 7:31 AM, Jochen Theodorou <blackdrag@...> wrote:
>  And may I ask what is left of Groovy if we use no closures? Is there
>  enough to have it still as a replacement for Java? Will you still want
>  to replace Java with Groovy in the cases where you need no MOP, no
>  Builder, no Grails and other things?

Excellent point.  When the discussion started I didn't think we would
lose closures...  If closures aren't even available in "fast annotated
methods" then that is a big hit to the "fast annotation" argument.
Thanks for the clarification.

-Tom

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email



Re: Groovy performance: what to do

by Charles Oliver Nutter-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Excellent summary of the problems with this proposal. I have some
comments below.

Jochen Theodorou wrote:
> Groovy has atm dynamic typing. Any change with a fast mode goals a more
> or less static system, which is a major change for such a language.
> There is either version 2, which will mean you can not mix dynamic typed
> parts and static typed parts in the same area and there is version 3
> which allows that, but will also give not many hints when it will do
> static and when it will do dynamic typing.

This is exactly what worried me. Because static typing goes through an
entirely different mechanism, it would be both confusing and problematic
for users. This is further complicated by the many users that would try
to take their Groovy code and "make it faster" by adding static types.
Suddenly dispatch rules would be completely different, and the code
would break.

> Some argue, that they would like to use Groovy, because it has a better
> syntax... for example with closures. Let us forget a moment about the
> GDK methods. Let us first look at a usage of Closures:

My opinion here is that it sounds like many people want Groovy features
in Java for certain pieces of code. I think that's a great idea...if
these features have proven useful we should consider adding them to Java
or consider making a static-typed Java-like language that supports them
if we can't push through actual Java language changes. Heck, even the
javac compiler toolchain is open-source now, so we could build off that.

But don't try to turn Groovy into "Java with extras" just because it
might solve a few performance problems. It wouldn't be Groovy.

> The way we want to go is to find a fast method selection process, where
> the selection will be cached at the place where the method call will be
> done (call site cache) and in later calls we will need only a
> verification step here, which can be much faster than the normal method
> selection and which probably can be inlined by the JIT together with the
> method call itself. This will mean that.

This is the technique that has been proven to work in JRuby, and it
would work for Groovy too. I'm willing to help make it happen (once I
find my misplaced 8th day of the week).

- Charlie

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email



Re: Groovy performance: what to do

by glaforge :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Sat, Feb 23, 2008 at 8:43 AM, Charles Oliver Nutter
<charles.nutter@...> wrote:
> Excellent summary of the problems with this proposal. I have some
>  comments below.

Agreed, that was an excellent summary.
In fact, I didn't think the consequences whould have gone that deep,
but with these explanations, it's pretty clear.
Thanks a lot, Jochen.

>  Jochen Theodorou wrote:
>  > Groovy has atm dynamic typing. Any change with a fast mode goals a more
>  > or less static system, which is a major change for such a language.
>  > There is either version 2, which will mean you can not mix dynamic typed
>  > parts and static typed parts in the same area and there is version 3
>  > which allows that, but will also give not many hints when it will do
>  > static and when it will do dynamic typing.
>
>  This is exactly what worried me. Because static typing goes through an
>  entirely different mechanism, it would be both confusing and problematic
>  for users. This is further complicated by the many users that would try
>  to take their Groovy code and "make it faster" by adding static types.
>  Suddenly dispatch rules would be completely different, and the code
>  would break.

Also, on a practical note, I hardly imagine the headaches when doing
user support on the mailing-lists, trying to figure out which call is
really static, which one is really dynamic, switching mental models
back and forth to figure out what's going on.

>  > Some argue, that they would like to use Groovy, because it has a better
>  > syntax... for example with closures. Let us forget a moment about the
>  > GDK methods. Let us first look at a usage of Closures:
>
>  My opinion here is that it sounds like many people want Groovy features
>  in Java for certain pieces of code. I think that's a great idea...if
>  these features have proven useful we should consider adding them to Java
>  or consider making a static-typed Java-like language that supports them
>  if we can't push through actual Java language changes. Heck, even the
>  javac compiler toolchain is open-source now, so we could build off that.

In a way, I believe C# has shown the way so far (especially the third
revision of it), by adding extension methods (our Groovy categories
more or less), anonymous functions (kinda like our closures), aonymous
types (a bit like our habit to return lists and maps in our Groovy
algorithms).

Java is evolving more slowly, unfortunately, but I hope it'll get some
of the goodness of Groovy in it, over time.
And as Charles says, if we find an 8th day in our weeks, it could be
fun prototyping this with OpenJDK or the multilanguage JVM work.

>  But don't try to turn Groovy into "Java with extras" just because it
>  might solve a few performance problems. It wouldn't be Groovy.

No comment, I can't agree more :-)

>  > The way we want to go is to find a fast method selection process, where
>  > the selection will be cached at the place where the method call will be
>  > done (call site cache) and in later calls we will need only a
>  > verification step here, which can be much faster than the normal method
>  > selection and which probably can be inlined by the JIT together with the
>  > method call itself. This will mean that.
>
>  This is the technique that has been proven to work in JRuby, and it
>  would work for Groovy too. I'm willing to help make it happen (once I
>  find my misplaced 8th day of the week).

You know, all your messages on these topics have already been of great
help and insight -- as well as those of John Wilson -- and we all
appreciate your efforts to help us. Being busy on JRuby, I'd
understand you can't find time to give us a hand, don't worry, but if
you do, that's cool :-)

Thanks Charlie for your comments.

--
Guillaume Laforge
Groovy Project Manager
G2One, Inc. Vice-President Technology
http://www.g2one.com

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email



Re: Groovy performance: what to do

by Martin C. Martin :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



Charles Oliver Nutter wrote:

> Excellent summary of the problems with this proposal. I have some
> comments below.
>
> Jochen Theodorou wrote:
>> Groovy has atm dynamic typing. Any change with a fast mode goals a
>> more or less static system, which is a major change for such a
>> language. There is either version 2, which will mean you can not mix
>> dynamic typed parts and static typed parts in the same area and there
>> is version 3 which allows that, but will also give not many hints when
>> it will do static and when it will do dynamic typing.
>
> This is exactly what worried me. Because static typing goes through an
> entirely different mechanism, it would be both confusing and problematic
> for users. This is further complicated by the many users that would try
> to take their Groovy code and "make it faster" by adding static types.
> Suddenly dispatch rules would be completely different, and the code
> would break.

What do you think of the proposal that is simply a hint?  The one where
you tell the compiler you expect given object classes and metaclasses?
There are two ways it could go:

- At runtime, if we don't have the expected classes & metaclasses,
ignore the hint and do what you would have done anyway.  This way, the
semantics aren't changed, but if the types are as expected the call is
much faster.  If not, it's a little slower.

- At runtime, if things don't match, signal an error.  This turns it
into an assertion mechanism.  This might be helpful in tracking down
bugs and making the programmer's intention clearer, as well as performance.

??

Best,
Martin

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email



Re: Groovy performance: what to do

by Jochen Theodorou :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Charles Oliver Nutter schrieb:
> Excellent summary of the problems with this proposal. I have some
> comments below.

sure thing ;)

[...]

>> Some argue, that they would like to use Groovy, because it has a
>> better syntax... for example with closures. Let us forget a moment
>> about the GDK methods. Let us first look at a usage of Closures:
>
> My opinion here is that it sounds like many people want Groovy features
> in Java for certain pieces of code. I think that's a great idea...if
> these features have proven useful we should consider adding them to Java
> or consider making a static-typed Java-like language that supports them
> if we can't push through actual Java language changes. Heck, even the
> javac compiler toolchain is open-source now, so we could build off that.

well, I tried to show that current Groovy Closures do not translate
nicely to a static typed system. If you want to provide direct method
calls for closures, then you need a method signature, that means the
name, the number of parameters, the types of the parameters and the
return type as well as a class that defines all this. If you have these
informations you can do all the nice compile time checks too, but that
is just a side effect here.

> But don't try to turn Groovy into "Java with extras" just because it
> might solve a few performance problems. It wouldn't be Groovy.

I agree.

>> The way we want to go is to find a fast method selection process,
>> where the selection will be cached at the place where the method call
>> will be done (call site cache) and in later calls we will need only a
>> verification step here, which can be much faster than the normal
>> method selection and which probably can be inlined by the JIT together
>> with the method call itself. This will mean that.
>
> This is the technique that has been proven to work in JRuby, and it
> would work for Groovy too. I'm willing to help make it happen (once I
> find my misplaced 8th day of the week).

hehe, I might contact you soon about this, maybe you will have some time
to replay to some mails.

bye blackdrag


--
Jochen "blackdrag" Theodorou
The Groovy Project Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/
http://www.g2one.com/

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email



Re: Groovy performance: what to do

by Jochen Theodorou :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Martin C. Martin schrieb:
[...]
> What do you think of the proposal that is simply a hint?  The one where
> you tell the compiler you expect given object classes and metaclasses?
> There are two ways it could go:
>
> - At runtime, if we don't have the expected classes & metaclasses,
> ignore the hint and do what you would have done anyway.  This way, the
> semantics aren't changed, but if the types are as expected the call is
> much faster.  If not, it's a little slower.

that's the way I want to go. With this we can speed up numeric
operations as well as many other method calls *without* changing the
semantics.

> - At runtime, if things don't match, signal an error.  This turns it
> into an assertion mechanism.  This might be helpful in tracking down
> bugs and making the programmer's intention clearer, as well as performance.

well... why should the compiler ever expect or not expect a part to be
dynamically? Somehow I can't think of how this way should work. Maybe I
don't understand what you mean yet.

bye blackdrag

--
Jochen "blackdrag" Theodorou
The Groovy Project Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/
http://www.g2one.com/

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email



Re: Groovy performance: what to do

by Charles Oliver Nutter-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Jochen Theodorou wrote:
> hehe, I might contact you soon about this, maybe you will have some time
> to replay to some mails.

Absolutely...and in fact I'm soon going to start taking all our code
generation, call site, and method handle subsystems and making them
generic so anyone can use them. Hopefully this will be useful for Groovy.

- Charlie

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email



Re: Groovy performance: what to do

by Martin C. Martin :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



Charles Oliver Nutter wrote:

> Excellent summary of the problems with this proposal. I have some
> comments below.
>
> Jochen Theodorou wrote:
>> Groovy has atm dynamic typing. Any change with a fast mode goals a
>> more or less static system, which is a major change for such a
>> language. There is either version 2, which will mean you can not mix
>> dynamic typed parts and static typed parts in the same area and there
>> is version 3 which allows that, but will also give not many hints when
>> it will do static and when it will do dynamic typing.
>
> This is exactly what worried me. Because static typing goes through an
> entirely different mechanism, it would be both confusing and problematic
> for users. This is further complicated by the many users that would try
> to take their Groovy code and "make it faster" by adding static types.
> Suddenly dispatch rules would be completely different, and the code
> would break.

Actually, we have static typing in Groovy:

def foo (String s) {1}
def foo (Object o) {2}

String a = "test"
Object b = a
def    c = a
def    d = b

// with Groovy style static typing
assert foo(a) == 1
assert foo((Object)b) == 2
assert foo(c) == 2
assert foo((Object)d) == 2

Which suggests two questions:

1. Since this has been in there for a while and hasn't caused problems
in existing code bases, would allowing a different syntax for the same
thing cause problems?  Right now we can say "in this particular use,
treat variable X as class C, even if it's of a class derived from C."
The proposed change would say "wherever this variable is used, treat it
as class C."  That means the declaration which determines the semantics
is removed from where its used, but that's no different from any other
declaration.  For example, "a = 23" can fail if a is of type, say, Map.
  And that declaration could be far away from the assignment line, but
people seem to handle that alright.

2. Could we use the existing syntax to do more at compile time and less
at runtime?  I think the answer at the moment is "no," because the types
are just given to the metaclass, and in general its an uncomputable
problem to tell what the metaclass will be at compile time.

But what if the programmer could annotate a class to say "all instances
of a given class use the same metaclass," and then have a way for the
metaclass to tell the compiler when a method could be determined at
compile time?

For example, if the Metaclass has a resolveMethod() method, then at
compile time we could instantiate the Metaclass with a no-arg
constructor and call resolveMethod() with the given types.  If it
returns a method, we could insert that call directly.  If it returns
None, we go back to inserting the normal
ScriptBytecodeAdapter.invokeMethod() call.

What do people think?

Best,
Martin

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email




Re: Groovy performance: what to do

by Martin C. Martin :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



Jochen Theodorou wrote:

> Martin C. Martin schrieb:
> [...]
>> What do you think of the proposal that is simply a hint?  The one
>> where you tell the compiler you expect given object classes and
>> metaclasses? There are two ways it could go:
>>
>> - At runtime, if we don't have the expected classes & metaclasses,
>> ignore the hint and do what you would have done anyway.  This way, the
>> semantics aren't changed, but if the types are as expected the call is
>> much faster.  If not, it's a little slower.
>
> that's the way I want to go. With this we can speed up numeric
> operations as well as many other method calls *without* changing the
> semantics.
>
>> - At runtime, if things don't match, signal an error.  This turns it
>> into an assertion mechanism.  This might be helpful in tracking down
>> bugs and making the programmer's intention clearer, as well as
>> performance.
>
> well... why should the compiler ever expect or not expect a part to be
> dynamically? Somehow I can't think of how this way should work. Maybe I
> don't understand what you mean yet.

You can think of the current method resolution like this:

(1) send the types to the metaclass and have it figure out what method
to invoke.

With the first proposal, this becomes:

(2)
     if (types & metaclass are as expected) {
        call associated method
     } else {
        send the types to the metaclass and have it figure out what
        method to invoke.
     }

The question is: if the programmer says they expect certain types &
metaclass, but at runtime we find something different, is that an error?
  Sometimes it will be, sometimes it won't be.  It depends on whether
the programmer was thinking "these types will usually be what I said,
but sometimes won't" vs. "from the way I designed the code, these
expressions should always have these types.  If they don't, something's
wrong."  For the latter, we get:

(3)
     if (types & metaclass are as expected) {
        call associated method
     } else {
        throw execption
     }

That makes the type declaration the same as an assertion.  You could
imagine having an optimized build which doesn't even check:

(4) call associated method

Of course, you'd only want to turn off the type checks after you've
thoroughly debugged, profiled, and found them to be a bottleneck.  (I
don't understand why Java even has a switch to turn off all assertions
globally; turning off the ones that aren't a bottleneck can only lead to
confusing messages or even corrupt data.  And it really boggles my mind
that they're off by default.  Oh well.)

Option (2) is essentially what call site caching does, where "expected"
is what was seen last time.  But it doesn't allow (3) or (4).  Whether
that's a problem or an advantage depends on your point of view.  ;)

Best,
Martin

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email




Re: Groovy performance: what to do

by Charles Oliver Nutter-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Martin C. Martin wrote:
> Actually, we have static typing in Groovy:

Actually, you don't have static typing in Groovy, you have a limited
type-checking syntax that happens at runtime.

Static typing would mean that at compile time you're binding to a
specific type and specific methods on that type. Groovy's type
declarations are only used to declare that a particular variable can
only accept values of a given type or its subtypes; no guarantees are
made about method binding since the set of methods on a given type may
be different at runtime (categories, expando).

Any attempt to force Groovy into "fully static mode" under certain
circumstances would require either checking for dynamic changes at
runtime or differing method dispatch semantics. The former would still
incur a performance hit and possibly eliminate some of the benefit of
static typing. The latter would not be Groovy.

- Charlie

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email




Re: Groovy performance: what to do

by Jochen Theodorou :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Martin C. Martin schrieb:
[...]

> Actually, we have static typing in Groovy:
>
> def foo (String s) {1}
> def foo (Object o) {2}
>
> String a = "test"
> Object b = a
> def    c = a
> def    d = b
>
> // with Groovy style static typing
> assert foo(a) == 1
> assert foo((Object)b) == 2
> assert foo(c) == 2
> assert foo((Object)d) == 2

are you sure? This should be:

assert foo(a) == 1
assert foo((Object)b) == 2
assert foo(c) == 1
assert foo((Object)d) == 2

and this should be mentioned too:

assert foo(b) == 1
assert foo(d) == 1

Groovy uses the Java idiom of casting a parameter to enable the
selection of a certain method.. I am not sure that this should be seen
as static or mixed typing.

> Which suggests two questions:
>
> 1. Since this has been in there for a while and hasn't caused problems
> in existing code bases,

well we added this before 1.0, because in some cases it is the only way
to select the right method.

> would allowing a different syntax for the same
> thing cause problems?  Right now we can say "in this particular use,
> treat variable X as class C, even if it's of a class derived from C."
> The proposed change would say "wherever this variable is used, treat it
> as class C."  That means the declaration which determines the semantics
> is removed from where its used, but that's no different from any other
> declaration.  For example, "a = 23" can fail if a is of type, say, Map.
>  And that declaration could be far away from the assignment line, but
> people seem to handle that alright.

looks like I can't follow you... yes, what you said about "a=23" is
true, but what is the point? Groovy compiles "a=23" as "a=(T)23", where
T is the type of a, as long as the type is known.... which means for
example, that for properties no cast happens.

> 2. Could we use the existing syntax to do more at compile time and less
> at runtime?  I think the answer at the moment is "no," because the types
> are just given to the metaclass, and in general its an uncomputable
> problem to tell what the metaclass will be at compile time.

do less at runtime and do more at compile time of what exactly? A method
selecton? Yes, I am positivce we can let the compiler guess the
method... or in other words let the compiler guess the initial method
used ofr the call site cache. But in general return types andtypes of
properties are unknown, so the compiler can't really do much more than
guessing in many cases.

> But what if the programmer could annotate a class to say "all instances
> of a given class use the same metaclass," and then have a way for the
> metaclass to tell the compiler when a method could be determined at
> compile time?

let us make this more easy by making it more special. Let us say there
is a way to say that always the default MetaClass will be used for all
objects. In that case we could for final classes and if all types of all
parameters are known generate a static call without loosing semantic.
final because of our multi methods. With this it can be can be
considered as rare case.

bye blackdrag

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email




Re: Groovy performance: what to do

by Jochen Theodorou :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Martin C. Martin schrieb:
[...]

> You can think of the current method resolution like this:
>
> (1) send the types to the metaclass and have it figure out what method
> to invoke.
>
> With the first proposal, this becomes:
>
> (2)
>     if (types & metaclass are as expected) {
>        call associated method
>     } else {
>        send the types to the metaclass and have it figure out what
>        method to invoke.
>     }
>
> The question is: if the programmer says they expect certain types &
> metaclass, but at runtime we find something different, is that an error?

if you want to keep the current way, then no. Not unless you add
additional syntax for extended checks.

[...]

> (4) call associated method
>
> Of course, you'd only want to turn off the type checks after you've
> thoroughly debugged, profiled, and found them to be a bottleneck.  (I
> don't understand why Java even has a switch to turn off all assertions
> globally; turning off the ones that aren't a bottleneck can only lead to
> confusing messages or even corrupt data.  And it really boggles my mind
> that they're off by default.  Oh well.)
>
> Option (2) is essentially what call site caching does, where "expected"
> is what was seen last time.  But it doesn't allow (3) or (4).  Whether
> that's a problem or an advantage depends on your point of view.  ;)

3 is not desired for us atm, and 4... essentially we need 3 to ensure we
did chose the right method. If there are cases where we can simplify the
code from 3 to 4, then it is good... for example I could imagine that we
do not check the MetaClass each time we invoke a method, but instead do
it block wise to reduce the costs... not sure yet

bye blackdrag

--
Jochen "blackdrag" Theodorou
The Groovy Project Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/
http://www.g2one.com/

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email




Re: Groovy performance: what to do

by Alexandru Popescu ☀ :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Mon, Feb 25, 2008 at 1:17 AM, Jochen Theodorou <blackdrag@...> wrote:

> Martin C. Martin schrieb:
>  [...]
>
> > Actually, we have static typing in Groovy:
>  >
>  > def foo (String s) {1}
>  > def foo (Object o) {2}
>  >
>  > String a = "test"
>  > Object b = a
>  > def    c = a
>  > def    d = b
>  >
>  > // with Groovy style static typing
>  > assert foo(a) == 1
>  > assert foo((Object)b) == 2
>  > assert foo(c) == 2
>  > assert foo((Object)d) == 2
>
>  are you sure? This should be:
>
>
>  assert foo(a) == 1
>  assert foo((Object)b) == 2
>  assert foo(c) == 1
>  assert foo((Object)d) == 2
>
>  and this should be mentioned too:
>
>  assert foo(b) == 1
>  assert foo(d) == 1
>

This is my expectation too... and I've just checked it against the
1.5.4 and it works as expected.

./alex
--
.w( the_mindstorm )p.

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email




Re: Groovy performance: what to do

by Martin C. Martin :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



Jochen Theodorou wrote:

> Martin C. Martin schrieb:
> [...]
>> Actually, we have static typing in Groovy:
>>
>> def foo (String s) {1}
>> def foo (Object o) {2}
>>
>> String a = "test"
>> Object b = a
>> def    c = a
>> def    d = b
>>
>> // with Groovy style static typing
>> assert foo(a) == 1
>> assert foo((Object)b) == 2
>> assert foo(c) == 2
>> assert foo((Object)d) == 2
>
> are you sure? This should be:
>
> assert foo(a) == 1
> assert foo((Object)b) == 2
> assert foo(c) == 1
> assert foo((Object)d) == 2

You're right; my 7 month old kid still wakes up twice in the middle of
the night, and the sleep deprivation is affecting me.  :)

>
> and this should be mentioned too:
>
> assert foo(b) == 1
> assert foo(d) == 1

Yes, the cast leads to static typing, which as you say, gives different
semantics than dynamic typing.

> Groovy uses the Java idiom of casting a parameter to enable the
> selection of a certain method.. I am not sure that this should be seen
> as static or mixed typing.
>
>> Which suggests two questions:
>>
>> 1. Since this has been in there for a while and hasn't caused problems
>> in existing code bases,
>
> well we added this before 1.0, because in some cases it is the only way
> to select the right method.
>
>> would allowing a different syntax for the same thing cause problems?  
>> Right now we can say "in this particular use,
>> treat variable X as class C, even if it's of a class derived from C."
>> The proposed change would say "wherever this variable is used, treat
>> it as class C."  That means the declaration which determines the
>> semantics is removed from where its used, but that's no different from
>> any other declaration.  For example, "a = 23" can fail if a is of
>> type, say, Map.  And that declaration could be far away from the
>> assignment line, but people seem to handle that alright.
>
> looks like I can't follow you... yes, what you said about "a=23" is
> true, but what is the point? Groovy compiles "a=23" as "a=(T)23", where
> T is the type of a, as long as the type is known.... which means for
> example, that for properties no cast happens.

It wasn't a big point, just that the declaration of "a" affects the
semantics of "a = 23."  One of Guillaume's concerns with including a
keyword/annotation for static typing was that we'd get posts to mailing
lists that an expression had unexpected results, and we'd have to guess
to ask them about the declaration of the variables.  I'm just pointing
out, we have the same issue already with "def" vs. typed variables.
It's a minor point.

>
>> 2. Could we use the existing syntax to do more at compile time and
>> less at runtime?  I think the answer at the moment is "no," because
>> the types are just given to the metaclass, and in general its an
>> uncomputable problem to tell what the metaclass will be at compile time.
>
> do less at runtime and do more at compile time of what exactly? A method
> selecton? Yes, I am positivce we can let the compiler guess the
> method... or in other words let the compiler guess the initial method
> used ofr the call site cache. But in general return types andtypes of
> properties are unknown, so the compiler can't really do much more than
> guessing in many cases.

Are there cases where you could skip runtime method selection entirely,
since you know it at runtime?

>
>> But what if the programmer could annotate a class to say "all
>> instances of a given class use the same metaclass," and then have a
>> way for the metaclass to tell the compiler when a method could be
>> determined at compile time?
>
> let us make this more easy by making it more special. Let us say there
> is a way to say that always the default MetaClass will be used for all
> objects. In that case we could for final classes and if all types of all
> parameters are known generate a static call without loosing semantic.
> final because of our multi methods. With this it can be can be
> considered as rare case.

That sounds great.  Do you think this is worth implementing, or would
the case be too rare?  Also, would the classes need to be final if mixed
with the casting syntax as above?  I think this could lead to its use in
cases that are a lot less rare.

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email



Re: Groovy performance: what to do

by Martin C. Martin :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



Jochen Theodorou wrote:

> Martin C. Martin schrieb:
> [...]
>> You can think of the current method resolution like this:
>>
>> (1) send the types to the metaclass and have it figure out what method
>> to invoke.
>>
>> With the first proposal, this becomes:
>>
>> (2)
>>     if (types & metaclass are as expected) {
>>        call associated method
>>     } else {
>>        send the types to the metaclass and have it figure out what
>>        method to invoke.
>>     }
>>
>> The question is: if the programmer says they expect certain types &
>> metaclass, but at runtime we find something different, is that an error?
>
> if you want to keep the current way, then no. Not unless you add
> additional syntax for extended checks.

Sorry, I'm not being very clear.  When I said "error" I was talking
about the programmer's intentions, I should have said "mistake" instead.
  In other words, I'm saying there are times when you want the extended
checks (and other times you don't.)  In those cases, it would be more
helpful for the runtime to signal an error than to continue on with
unintended (but valid according to the specs) semantics.

>
> [...]
>> (4) call associated method
>>
>> Of course, you'd only want to turn off the type checks after you've
>> thoroughly debugged, profiled, and found them to be a bottleneck.  (I
>> don't understand why Java even has a switch to turn off all assertions
>> globally; turning off the ones that aren't a bottleneck can only lead
>> to confusing messages or even corrupt data.  And it really boggles my
>> mind that they're off by default.  Oh well.)
>>
>> Option (2) is essentially what call site caching does, where
>> "expected" is what was seen last time.  But it doesn't allow (3) or
>> (4).  Whether that's a problem or an advantage depends on your point
>> of view.  ;)
>
> 3 is not desired for us atm, and 4... essentially we need 3 to ensure we
> did chose the right method. If there are cases where we can simplify the
> code from 3 to 4, then it is good... for example I could imagine that we
> do not check the MetaClass each time we invoke a method, but instead do
> it block wise to reduce the costs... not sure yet

It sounds like you don't want to give the programmer the ability to
override the default behavior.  You don't want the programmer to be able
to say "just find the method based on these types.  Even if you can't
prove it at compile time, trust me, these really are the types."  You
always want to check the declared types, in case the programmer makes a
mistake.  Essentially, when it comes to typing for efficiency, you never
want to disable what amount to assertions.  Am I understanding correctly?

I can see why you'd want to do that in places where performance isn't
critical, as with any assertion.  Perhaps it is a differing philosophy,
but it makes sense to me to be able to turn those off in the small
amount of code that's a performance bottleneck.

Or am I misunderstanding?

Best,
Martin

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email



Re: Groovy performance: what to do

by Jochen Theodorou :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Martin C. Martin schrieb:

>
>
> Jochen Theodorou wrote:
>> Martin C. Martin schrieb:
>> [...]
>>> Actually, we have static typing in Groovy:
>>>
>>> def foo (String s) {1}
>>> def foo (Object o) {2}
>>>
>>> String a = "test"
>>> Object b = a
>>> def    c = a
>>> def    d = b
>>>
>>> // with Groovy style static typing
>>> assert foo(a) == 1
>>> assert foo((Object)b) == 2
>>> assert foo(c) == 2
>>> assert foo((Object)d) == 2
>>
>> are you sure? This should be:
>>
>> assert foo(a) == 1
>> assert foo((Object)b) == 2
>> assert foo(c) == 1
>> assert foo((Object)d) == 2
>
> You're right; my 7 month old kid still wakes up twice in the middle of
> the night, and the sleep deprivation is affecting me.  :)

ah, the kid will grow and sleep through, and then he will give you other
problems where you wish it would be only a matter of sleeping through ;)

[...]

>>  yes, what you said about "a=23" is
>> true, but what is the point? Groovy compiles "a=23" as "a=(T)23",
>> where T is the type of a, as long as the type is known.... which means
>> for example, that for properties no cast happens.
>
> It wasn't a big point, just that the declaration of "a" affects the
> semantics of "a = 23."  One of Guillaume's concerns with including a
> keyword/annotation for static typing was that we'd get posts to mailing
> lists that an expression had unexpected results, and we'd have to guess
> to ask them about the declaration of the variables.  I'm just pointing
> out, we have the same issue already with "def" vs. typed variables. It's
> a minor point.

yes, that's true.

>>> 2. Could we use the existing syntax to do more at compile time and
>>> less at runtime?  I think the answer at the moment is "no," because
>>> the types are just given to the metaclass, and in general its an
>>> uncomputable problem to tell what the metaclass will be at compile time.
>>
>> do less at runtime and do more at compile time of what exactly? A
>> method selecton? Yes, I am positivce we can let the compiler guess the
>> method... or in other words let the compiler guess the initial method
>> used ofr the call site cache. But in general return types andtypes of
>> properties are unknown, so the compiler can't really do much more than
>> guessing in many cases.
>
> Are there cases where you could skip runtime method selection entirely,
> since you know it at runtime?

If the compiler guesses a method, then we have to validate that guess,
not only because the guess might be wrong, but also because the
MetaClass might have changed and that change could affect the current
method selection... well and because a category could be active,
overwriting the call we originally wanted to do.

>>> But what if the programmer could annotate a class to say "all
>>> instances of a given class use the same metaclass," and then have a
>>> way for the metaclass to tell the compiler when a method could be
>>> determined at compile time?
>>
>> let us make this more easy by making it more special. Let us say there
>> is a way to say that always the default MetaClass will be used for all
>> objects. In that case we could for final classes and if all types of
>> all parameters are known generate a static call without loosing
>> semantic. final because of our multi methods. With this it can be can
>> be considered as rare case.
>
> That sounds great.  Do you think this is worth implementing, or would
> the case be too rare?  Also, would the classes need to be final if mixed
> with the casting syntax as above?  I think this could lead to its use in
> cases that are a lot less rare.

there is another class of methods that could theoretically be called
directly and that is private methods. And I think implementing this for
private methods is worth it, the implementation for other methods would
be a side product then. Ah yes.. not the method needs to be final, the
class needs to be, because this way we can be sure there will be no
subclass adding a method... but I guess we can't work around the check
here too.. because it is always possible, that the MetaClass got a new
overloading or replacing method.... so this check has to check at last
the MetaClass for being the default.

bye blackdrag

--
Jochen "blackdrag" Theodorou
The Groovy Project Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/
http://www.g2one.com/

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


< Prev | 1 - 2 - 3 - 4 | Next >