gwtextreme-1213250644043195-8
TRANSCRIPT
![Page 1: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/1.jpg)
![Page 2: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/2.jpg)
GWT Extreme!Performance and FlexibilityRay Cromwell, CTO, Timefire, Inc05/29/2008
![Page 3: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/3.jpg)
BUDD: Why did he call it GWT Extreme?
BILL: I guess he thought it sounded kinda cool.
![Page 4: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/4.jpg)
Extreme Performance and Flexibility
• “Faster (and Smaller) than Possible” code• Parsing and Evaluating CSS Selector Queries• High Performance Graphics
• Bridging GWT with other execution environments• Remote procedure calls to Android, Flash, and Gears
• Writing Flash and Gears Workers in Java• Tricks to compile subsets of your source as separate
packages• Q&A if time permits
![Page 5: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/5.jpg)
GWT Bloated and Slow? Think Again
• Faster• Generate Java code on the fly at compile time• Compiler inlines small Java and Javascript methods• Devirtualizes most other method calls• And tons more, too many to list….
• Smaller• Prunes and eliminates anything not used• Aggressively obfuscates code
• Obfuscated identifiers chosen to maximize DEFLATE compression• Replace runtime operations with compile time
“Faster and Smaller than Possible” Code
![Page 6: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/6.jpg)
GwtQuery (aka GQuery)
• JQuery-like API in GWT• Uses GWT 1.5 language features for succinct code• Run-time CSS3 Selector parsing and evaluation• Compile-time CSS3 Selector parsing• Leverages modern browser features when available:
• XPath (document.evaluate)• W3C CSS Selector API (document.querySelectorAll)• getElementsByClassName()
![Page 7: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/7.jpg)
GwtQuery Example
Runtime Evaluation
• Find all “menus”, make first element text “Hello”
import gwtquery.client.GwtQuery;import static gwtquery.client.GwtQuery.$;
public class GwtQueryModule implements EntryPoint { public void onModuleLoad() { $(“ul.menu > li:first-child”).html(“hello”); }}
![Page 8: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/8.jpg)
GwtQuery Example
What does the $(selector) function translate into?
• On Safari 3.1• document.querySelectorAll(selector)• On Firefox, Opera, older Safari• Lots of Regexp parsing to compute xpathExpression• document.evaluate(xpathExpression)• On IE < 8 and others, a bunch of Regexp and DOM calls• Note: Each browser gets separately compiled JS
![Page 9: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/9.jpg)
Digression: Generators
• Feature of Deferred Binding Mechanism• GWT.create(RequestedType.class)• Replace requested type with generated implementation• Turns into new GeneratedType()
![Page 10: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/10.jpg)
GwtQuery Example
Compile-time parsing
• Selectors usually literal strings, known at compile time• Why parse and translate these at runtime?!• Perform parsing and translation to XPath or JS-DOM
navigation calls at compile-time
public MySelectors extends Selectors { @Selector(“ul.menu > li:first-child”) GQuery allFirstMenuItems();}
MySelectors selector = GWT.create(MySelectors.class);
selector.allFirstMenuItems().html(“hello”);
![Page 11: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/11.jpg)
GwtQuery Example
Compile-time parsing
• GWT.create(MySelectors.class) triggers Generator• Different Generator for each browser (DOM, XPath, etc)• Generator creates implementation of MySelectors interface• For each method with a @Selector annotation• Parses CSS Selector, emits implementation of method• Compiler inlines method, elides everything else
![Page 12: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/12.jpg)
GwtQuery Example
Compile Time Parsing: Bottom Line
ul > li:first-child
becomes
document.evaluate(“ul/li[position() = 1]”)
![Page 13: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/13.jpg)
GwtQuery Example
How big is the output?
• jQuery 1.2.3• ~3400 lines of Javascript• 98kb unprocessed source• 15kb obfuscated and gzipped• GwtQuery• ~3400 lines of Java• 116kb on disk• How big is it compiled?• 15kb or larger?• How about 7kb, a 50% reduction?• 3kb sounds about right!• 712 bytes is the answer!• Smaller than single packet, HTTP headers
![Page 14: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/14.jpg)
Caveats and Objections
• Trivial example• More reasonable example would exercise larger part of API• and reduce amount of pruned code• Example shows how aggressive GWT optimizer is• past GWT critics have used Hello World examples to
demonstrate purported “bloat”
![Page 15: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/15.jpg)
Demo: Progressively Enhancing <UL> into PowerPoint-like slide transitionsSample Code
<div class="slide transition-fade"> Slide 1 <ul class="transition-fade"> <li>Point One</li> <li>Point Two</li> <li>Point Three</li> </ul></div><div class="slide transition-fade"> Slide 2 <ul class="transition-appear"> <li>Slide 2 Point One</li> <li>Slide 2 Point Two</li> <li>Slide 3 Point Three</li> </ul></div>
![Page 16: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/16.jpg)
GwtQuery code
Sample Code for Selectors needed
interface Slide extends Selectors { // find all LI elements rooted at ctx @Selector("li") NodeList<Element> slideBulletsCtx(Node ctx);
// Find all DIV elements with class 'slide' @Selector("div.slide") NodeList<Element> allSlides(); }
![Page 17: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/17.jpg)
GwtQuery code
Sample Code for Event Handling
final Slide s = GWT.create(Slide.class);$(Document.get().getBody()).click(new Function() { int curSlide = 0; int curBullet = 0; GQuery slides = $(s.allSlides()); GQuery bullets = $(s.slideBulletsCtx(slides.get(curSlide)));
public boolean f(Event e) { if (curBullet < bullets.size()) bullets.eq(curBullet++).as(Effects).fadeIn(); else bullets.css("opacity","0"); slides.eq(curSlide).css("display", "none"); curSlide++; if(curSlide == slides.size()) curSlide = 0; curBullet = 0; bullets = $(s.slideBulletsCtx(slides.get(curSlide))); slides.eq(curSlide).css("display","block") .as(Effects).fadeIn(); return true; }});
![Page 18: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/18.jpg)
Sample of Generated Output for Selector “.slide li”
W3C Selector API version
public class SlideNativeImpl extends SelectorEngine implements MySelectors { public final NodeList<Element> slideBullets() { return querySelectorAll(".slide li"); }}
![Page 19: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/19.jpg)
Sample of Generated Output for Selector “.slide li”
XPath Version
public class SlideXPathImpl extends SelectorEngine implements Slide { public final NodeList<Element> slideBullets() { return xpathEvaluate("./descendant::*[contains(concat(' ', @class, ' '), ' slide ')]/descendant::li"); }}
![Page 20: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/20.jpg)
GWT Query
• Alpha Released Today• Available at http://gwtquery.com• Help Contribute to Core and Plugins!
![Page 21: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/21.jpg)
High Performance Graphics
![Page 22: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/22.jpg)
Extreme Graphics Performance
• Immediate Mode vs Retained Mode– Canvas vs SVG/VML
• JS VMs top out at between 1000-10000 method calls on Canvas
• Can we cache/reuse work?• Take a page from OpenGL’s Playbook:
Display Lists
![Page 23: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/23.jpg)
Extreme Graphics Performance: Display Lists
• Record a sequence of draw calls• Replay sequence like a macro• Framework/driver can perform optimizations
– Collapse sequence of scale/rotate/translate operations into setTransform call
– Cull/Clip some operations if possible– Cache result as bitmap where possible
• DEMO!
![Page 24: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/24.jpg)
Extreme Graphics Performance and Flexibility:Chronoscope Chart Library
• 20,000 lines of code– 500kb of source– compiles to 58kb compressed
• 30,000+ points at interactive rates• Javascript, Flash, Applet, Servlet, and Android• Multi-grained API
– Full control with Java+GWT– Higher level with Javascript API– Or with no coding at all via Microformats and CSS
• DEMO!
![Page 25: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/25.jpg)
Some insights from porting to GWT 1.5
• Method inlining yields up to 100% perf gains• Ability to inline JSNI provided huge gains for
IE/Flash version• Slight increase in size • Abstractions don’t hurt much• Beware usage of long, costs of non-double
types• Static initializers can be harmful
![Page 26: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/26.jpg)
Chronoscope and Mobile Code with GWT
• Platform neutral code • Only 4 classes needed to run in other
environments or on the “cloud”– Flash, Android, Applet, Servlet
• GWT methods automatically exported to Javascript via GWT-Exporter library
![Page 27: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/27.jpg)
Integrating GWT with other Environments
![Page 28: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/28.jpg)
Integrating GWT with other environments
• GWT already integrates with Servlets• JSNI is used to integrate with Browser/JS• Extend RPC model to arbitrary containers
– Android– Flash– Gears Workers
![Page 29: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/29.jpg)
Example: Syndroid
Gadgets can span many Platforms
Android iGoogle OSX GoogleDesktop
Yahoo
And many Flash widget startups
![Page 30: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/30.jpg)
Example: Syndroid
• Synthesis of Android and GWT• Write Gadgets to a restricted API• Compile to Javascript or Dalvik or (later)
Actionscript• Deploy on Android, iGoogle, OSX, Yahoo,
et al• Prototype DEMO!
![Page 31: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/31.jpg)
Example: Android Native Interface
What if Android browser had a window.locationService object?
public class LocationServiceClient implements LocationService { public native String getLocation() /*-{ return $wnd.locationService.getLocation(); }-*/;}
![Page 32: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/32.jpg)
Generators + Linkers = Awesomeness
• Define RPC interface (sync or async)• Use Generator to generate client stub
• Params may or may not need to be serialized• Also generate “server” to handle request• “Server” handling code may need
bootstrapping• Linker used to generate bootstrap code• If needed, use Linker to package/compile
![Page 33: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/33.jpg)
Android Native InterfaceAndroidNativeInterface
LocationService
String getLocation();
extends
LocationServiceClient
String getLocation() { return $wnd.locationService.getLocation();}
implements
Emitted by Generator
LocationServiceImpl
String getLocation() { return ...android native code...}
impl
Written by Developer
Android Bootstrap
Bind LocationServiceImpl towindow.locationService
Provided by Linker
![Page 34: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/34.jpg)
Example: Android Native Interface
Synchronous RPC
public interface AndroidNativeInterface {}
@ANIBinding("locationService")@ImplementedBy("LocationServiceImpl")public interface LocationService extends AndroidNativeInterface { String getLocation();}
![Page 35: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/35.jpg)
Example: Android Native Interface
Implement Android side (not legal GWT code!)
public class LocationServiceImpl implements LocationService { public String getLocation() { try { Location currentLocation = ((LocationManager) context.getSystemService(Context.LOCATION_SERVICE)) .getCurrentLocation("gps");
return "Lat: "+currentLocation.getLatitude()+ ", Long: "+currentLocation.getLongitude(); } catch (Throwable e) { return "ExceptionInNativeAndroid:"+e.getClass().getName()+": "+e.getMessage(); } }}
![Page 36: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/36.jpg)
Example: Android Native Interface
To use
LocationService service = GWT.create(LocationService.class);Window.alert(“Your location is: “+service.getLocation());
![Page 37: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/37.jpg)
Example: Linker Generated BootstrapActivity
LocationServiceImpl gets exposed as window.locationService
public class BootstrapActivity extends Activity { @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(getBootstrapView()); } public WebView getBootstrapView() { WebView wv=new WebView(this); wv.getSettings().setJavaScriptEnabled(true); wv.getSettings().setUseDesktopUserAgent(true); wv.getSettings().setLoadsImagesAutomatically(true); wv.addJavascriptInterface(new ContactsServiceImpl(this), "contactsService"); wv.addJavascriptInterface(new LocationServiceImpl(this), "locationService"); wv.loadUrl("file:///android_asset/index.html"); return wv; }}
@ImplementedBy
@ANIBinding
![Page 38: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/38.jpg)
Example: Linker Generated Manifest
Needed by Android
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="syndroid.demo.SyndroidDemo"><uses-permission android:name="android.permission.ACCESS_LOCATION"/><uses-permission android:name="android.permission.ACCESS_GPS"/><uses-permission android:name="android.permission.ACCESS_ASSISTED_GPS"/> <application> <activity android:name="BootstrapActivity" android:label="SyndroidDemo"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application></manifest>
![Page 39: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/39.jpg)
Example: Linker Generated Build Script
Used to compile and package APK file
mkdir resmkdir classes$ANDROID_HOME/tools/aapt compile -m -J src -M AndroidManifest.xml -I $ANDROID_HOME/android.jarfind src -name '*.java' -print >src.listjavac -cp $ANDROID_HOME/android.jar @src.list -d classes$ANDROID_HOME/tools/dx -JXmx384M --dex --output=classes.dex -- locals=full --positions=lines classes/$ANDROID_HOME/tools/aapt package -f -c -M AndroidManifest.xml -A assets -I $ANDROID_HOME/android.jar SyndroidDemo.apkzip SyndroidDemo.apk classes.dex
![Page 40: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/40.jpg)
Client Stub Generator
• Use @ImplementedBy annotation to find Android implementing class
• Copy this class as resource (for Linker step)• Generate new Client stub
– Generate JSNI native method on Client Stub– JSNI method invokes Javascript object named by
@ANIBinding annotation
![Page 41: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/41.jpg)
Generator to Linker Communication
• Generators work on types, can’t see build artifacts (compiler output)
• Linkers work out build artifacts, can’t explore the type system
• Some Linkers need type information– e.g. Bootstrap scripts, manifests
• Communicate with linker by emitting a build artifact (e.g. text file)
• Linker can scan for this special file and read contents
• In our case, we write out mapping of @ANIBinding to @ImplementedBy
![Page 42: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/42.jpg)
Using Linker Generate Bootstrap/Package for APT
• Read info from Generator (ANIBindings/ImplementedBy)
• Copy implementation classes to build dir• Copy public resources to assets dir• Generate Android Manifest.xml• Generate Android Bootstrap Activity
– Set WebView as view– Enable Javascript– For each ANIBinding, bind instance of
implementing class to Javascript• Run Android Tools
– javac– dx– aapt to create final .apt
![Page 43: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/43.jpg)
Future Directions
• Use Special GWT bootstrap script to detect Android browsers
• Offer user choice of “over the air” provision of Android-specific app
• See http://timepedia.blogspot.com/2008/01/project-syndroidsynthesis-of-gwt-and.html for detailed architecture
![Page 44: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/44.jpg)
Compiling GWT to Flash
![Page 45: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/45.jpg)
Reusing the same Design Pattern for Flash
• Define ActionScriptNativeInterface• Place all “Flash” java code in .flash package
– Use generator to copy it to output as a resource• Use Generator to create JSNI stubs to invoke
Flash methods• But how do we turn Java code into SWF for
the server side?
![Page 46: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/46.jpg)
ActionScript Native InterfaceActionScriptNativeInterface
DrawService
void drawLine(x,y);
extends
DrawServiceClient
void drawLine(int x, int y) { $wnd.flashPlugin.drawLine(x, y);}
implements
Emitted by Generator
package foo.flash;
native void drawLine(int x, int y) /*-{ ... actionscript code to draw line ... }-*/;
impl
Written by Developer
Flash Bootstrap
generate main()
Export drawLine(x,y) via ExternalInterface
Provided by Linker
![Page 47: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/47.jpg)
Compiling Java to ActionScript with GWT
• IDEA: Invoke GWT compiler recursively• Use Linker to create new GWT Project • Copy “flash” Java code to source path • Emit Module.gwt.xml file• Generate entrypoint
– For each ActionScriptNativeInterface add ExternalInterface
• Invoke GWT Compiler to produce SWF?• Emit SWF as output artifact
![Page 48: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/48.jpg)
Packaging GWT output as SWF?
• GWT Compiler produces JS• Avoid GWT APIs which call DOM JSNI
methods– JRE generally safe
• Use Linker to– add custom bootstrap script to invoke EntryPoint– invoke Flex3 SDK in non-strict mode– Emit resulting SWF as output artifact
• Generator+Linker+Generator+Linker Pattern
![Page 49: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/49.jpg)
Writing Gears Workers in GWT
• Reuse same pattern as Flash– e.g. place Gears-translatable Java in ‘.gears’
package• Use Async RPC interfaces• JSON to marshal simple object types to Gears
and back• Use SSO-like Linker
![Page 50: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/50.jpg)
Q&A?
• GwtQuery available at– http://gwtquery.com
• Chronoscope available – http://timepedia.org
• For in-depth articles/code, see blog at:– http://timepedia.blogspot.com
• Upcoming articles on Syndroid, and ActionScriptNativeInterface
![Page 51: gwtextreme-1213250644043195-8](https://reader035.vdocument.in/reader035/viewer/2022070302/547316a2b4af9f987f8b456b/html5/thumbnails/51.jpg)