it makes quite a difference in speed.
Since running an 'ant' build invokes the GWT compiler on the samples,
I notice that it runs more quickly . Before, after changing a few
files I would notice a build time of over 4 minutes. Now it is down to
3 mins 30 secs on my workstation.
But now I am seeing a problem and cannot launch my HelloMaps demo
anymore (using the trunk source for everything) I am using the 2nd
version of Toby's patch.
[ERROR] Failed to create an instance of
'com.google.gwt.user.client.ui.impl.FocusImpl' via deferred binding
java.lang.IllegalArgumentException:
invokeNativeObject(@com.google.gwt.user.client.ui.impl.FocusImplOld::createBlurHandler()):
Cannot convert to type java.lang.Object from class Function
at com.google.gwt.dev.shell.JsValueGlue.get(JsValueGlue.java:223)
at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:249)
at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:113)
at com.google.gwt.user.client.ui.impl.FocusImplOld.createBlurHandler(FocusImplOld.java:95)
at com.google.gwt.user.client.ui.impl.FocusImplOld.<init>(FocusImplOld.java:31)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:494)
at com.google.gwt.dev.shell.ModuleSpace.rebindAndCreate(ModuleSpace.java:388)
at com.google.gwt.dev.shell.JavaScriptHost.rebindAndCreate(JavaScriptHost.java:153)
--
> at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject (JavaScriptHost.java:113)
> at com.google.gwt.user.client.ui.impl.FocusImplOld.createBlurHandler(FocusImplOld.java:95)
> at com.google.gwt.user.client.ui.impl.FocusImplOld.<init>(FocusImplOld.java :31)
> at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
> at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java :27)
> at java.lang.reflect.Constructor.newInstance(Constructor.java:494)
> at com.google.gwt.dev.shell.ModuleSpace.rebindAndCreate(ModuleSpace.java:388)
> at com.google.gwt.dev.shell.JavaScriptHost.rebindAndCreate (JavaScriptHost.java:153)
Hi Toby,
This is awesome! Okay, here's my review:
There are a number of sort/format issues not worth calling out specifically; I just reformatted the files correctly and attached a new patch file. The rest of the review is based on the corrected patch.
AbstractCompiler:
- defaultPolicy should be a constant; final and named DEFAULT_POLICY
- setCachePolicy() is coded defensively, which we avoid doing without a good reason. I would just do a blind set here. If later we think a caller might need to set a default policy, we can always make the static DEFAULT_POLICY public.
CacheManager:
- 638-639: dingleberry?
- all the "first time" stuff is now unreferenced and should die.
UISuite: Is this change related to your patch?
PerfLogger:
- We don't use @author tags.
- package-protected seems the wrong access level for the members of PerfLogger.Timing
- I don't understand the purpose of the log() method.. why would logging something cause the current perf frame to not save its timing? Practically speaking, you have no callers to log() so maybe just kill it and dontSaveTiming?
- The way the parents/subTimings stuff is arranges seems overly complicated. In practice, won't you always be modeling a pure stack? It seems like a (doubly) linked list would suffice. Am I missing something? If you have to make specific calls to do something different for isRoot(), then why not just initialize the current timing to null and use null checks instead? I don't understand the value of having a root object.
- I notice that in all uses of this class, start() and end() are called in straight-line code. I would have expected something like:
try {
PerfLogger.start(...);
// do the thing being timed
} finally {
PerfLogger.end();
}
Can you comment on the implications of an exception being thrown which prevents PerfLogger.end() from getting called?
Scott
On Jan 11, 2008 3:39 PM, Scott Blum < sco...@google.com> wrote:
Hi Toby,
There are a number of sort/format issues not worth calling out specifically; I just reformatted the files correctly and attached a new patch file. The rest of the review is based on the corrected patch.
- package-protected seems the wrong access level for the members of PerfLogger.Timing
Its access specifiers are set as per my intention: its basically a struct that is private to PerfLogger. I believe that adding accessors/mutators would only serve to obfuscate the code.
- I don't understand the purpose of the log() method.. why would logging something cause the current perf frame to not save its timing? Practically speaking, you have no callers to log() so maybe just kill it and dontSaveTiming?
- The way the parents/subTimings stuff is arranges seems overly complicated. In practice, won't you always be modeling a pure stack? It seems like a (doubly) linked list would suffice. Am I missing something? If you have to make specific calls to do something different for isRoot(), then why not just initialize the current timing to null and use null checks instead? I don't understand the value of having a root object.
These two questions are related. Basically, using log() lets you interject log statements into the current context without creating new entries on the "stack". The log statements go in as sibling nodes. I originally had some uses of log in AbstractCompiler but lost them along the way. I've re-added the most useful one.
On Jan 11, 2008 4:19 PM, Toby Reyelts <to...@google.com> wrote:- package-protected seems the wrong access level for the members of PerfLogger.Timing
Its access specifiers are set as per my intention: its basically a struct that is private to PerfLogger. I believe that adding accessors/mutators would only serve to obfuscate the code.
I agree with the struct itself being private, but if its members are being directly accessed from PerfLogger, while not make them public? Package-protected doesn't make sense to me.
- I don't understand the purpose of the log() method.. why would logging something cause the current perf frame to not save its timing? Practically speaking, you have no callers to log() so maybe just kill it and dontSaveTiming?
- The way the parents/subTimings stuff is arranges seems overly complicated. In practice, won't you always be modeling a pure stack? It seems like a (doubly) linked list would suffice. Am I missing something? If you have to make specific calls to do something different for isRoot(), then why not just initialize the current timing to null and use null checks instead? I don't understand the value of having a root object.
These two questions are related. Basically, using log() lets you interject log statements into the current context without creating new entries on the "stack". The log statements go in as sibling nodes. I originally had some uses of log in AbstractCompiler but lost them along the way. I've re-added the most useful one.
How about the more general comment that it seems a bit over complicated for what it's doing?
These two questions are related. Basically, using log() lets you interject log statements into the current context without creating new entries on the "stack". The log statements go in as sibling nodes. I originally had some uses of log in AbstractCompiler but lost them along the way. I've re-added the most useful one.
How about the more general comment that it seems a bit over complicated for what it's doing?
No, I think it's about six one way, half-a-dozen the other. By treating log messages like timing nodes, I have to write almost no special-casing for them. By instantiating a root node, it simplifies the creation of the ThreadLocals.
While looking over the Timing class, though, I did notice getDepth() is no longer being used, so I've pruned that from the patch.
I agree with the struct itself being private, but if its members are being directly accessed from PerfLogger, while not make them public? Package-protected doesn't make sense to me.
I think it makes the most sense for it to be exactly what it is. Perhaps it would be clearer if we thought about the runtime access behavior? If Timing fields were public, other classes could reflect on them and get access to them - that certainly doesn't match my intent. I could go the other way and make them private, but that doesn't really gain any benefit - the compiler would synthesize package protected methods on PerfLogger to access them anyway.
Hey Toby,
I know there are still issues getting IntelliJ to format in a way that doesn't introduce bogus diffs vs. Eclipse formatting, so I went ahead and did a cleanup again on the latest patch. Please use the first attached patch which 1) removes the whitespace diffs and 2) fixes a conflict against the HEAD revision.
I attached as a second patch my suggestions on how PerfLogger could be implemented to illustrate my point. In this version, I've made public those methods visible to the enclosing type and made the rest private (and not accessed from the outer class). I think this conveys the design of the Timing class a bit better. I have to admit that based on what you said, I don't see the reflection argument as a good enough reason to not convey the most correct semantic intent.
A couple of notes about the suggested version of PerfLogger:
1) My reasoning on moving more logic into the constructor was so we could do all of the maintenance work BEFORE reading System.nanoTime(); in particular the synchronized call to currentTiming.set() happens before the start time is read.
2) The reason isRoot() can go away is that, in particular, the root node could NEVER have had more than one child at a time because that child was printed and cleared when the root became active.
3) The other nice thing about getting rid of isRoot() is that it unmasked (for me) the fact that PerfLogger.log() did not have an "enabled" guard.
-Ray
> particular the synchronized call to currentTiming.set () happens before the
-Ray
Toby man, wow. I have noticed HUGE improvements in hosted mode, and it
fantastic. I have a low end dual core box and hosted mode really was
too slow, but I suffered through. Well no more! Start up time of
hosted more is now palatable, and the screen refreshes and general
responsiveness is amazing.
THANK YOU!!
Anything I can do to help test, just let me know...
Another +1. The speed improvements from this patch have had a profound
impact on our GWT development. Less surfing the web while launching
the application. :)
Has this patch found its way into the trunk yet?