|
View:
New views
20 Messages
—
Rating Filter:
Alert me
|
| < Prev | 1 - 2 - 3 - 4 | Next > |
|
|
Re: Groovy performance: what to doHi 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 doThe 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 |
|
|
|
|
|
Re: Groovy performance: what to doHi 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 doOn 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 doExcellent 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 doOn 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 doCharles 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 doCharles 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 doMartin 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 doJochen 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 doCharles 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 doJochen 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 doMartin 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 doMartin 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 doMartin 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 doOn 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 doJochen 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 doJochen 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 doMartin 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 > |
| Free embeddable forum powered by Nabble | Forum Help |