Hi Sam; I'm currently trying to get some functions written in clojure(-script) running on Android, wrapping them in a java class generated by rhino.
Currently, I'm stuck at overcoming the 64k limit. Could you explain the splitting process in some greater detail? All the best, Gerrit PS ~ Any eta on Lambdroid? Am Samstag, 22. November 2014 04:18:21 UTC+1 schrieb Sam Beran: > > The code is still half-baked, but in leu of a blog post or code, I can > summarize my reasoning and approach: > > > *ClojureScript is Designed With UI Responsiveness In Mind* > > At present, JVM Clojure is not currently suitable for Android development. > Since Android applications are structured around ephemeral Activities, > any startup penalty over 250 ms is simply unacceptable. Current benchmarks > [1] are showing 2-5 seconds of startup time, and I have seen no > straightforward advice on how to achieve an order-of-magnitude increase in > startup performance. ClojureScript (and JavaScript) is designed from the > ground up with startup speed in mind. ClojureScript can be used to create > responsive user interfaces on Android. > > > *Selecting a Host Runtime* > > In order to run ClojureScript on Android, I considered the following > options for host runtimes: > > - *Android WebView * - we can achieve reasonable startup times with a > WebView, however any data must be serialized and deserialized in order to > communicate between a WebView and Java. Even worse, any long-running > object > lifecycles must be manually managed, since we cannot rely on garbage > collection to maintain object references between the host VM and those of > the WebView. > - *V8 (JNI) - *I briefly considered compiling a V8 runtime to host > ClojureScript. Startup speed would probably outperform the WebView. This > would be a lot of work to develop a nice bridging mechanism. Object > lifecycle management is better than WebView, but still not ideal. With no > C++ or JNI background, I could tell very quickly that this would not be a > "weekend project". > - *Rhino* - Rhino is a lightweight JavaScript runtime for the JVM. > Execution speed is not fast, and since Rhino is not actively maintained, > it > will probably never support ES6 - not huge concerns for ClojureScript. > Since Rhino is a pure-Java runtime, there is very little overhead when > communicating between JS<-> Java, and Java GC can be used to maintain > object lifecycles. > - *Nashorn *- the successor to rhino. Not an option until Android > supports InvokeDynamic.[2] > > > > *Achieving Fast Startup on Rhino* > > When I initially ran ClojureScript on Rhino, Startup speed was around 8-10 > seconds - even worse than JVM Clojure! Some quick measurements indicated > that the bulk of the time was spent with Rhino parsing the JS sources for > cljs/core.js. I was pleased to discover that Rhino supports bytecode > precompilation via the jsc utility [3]. I was able to precompile the > ClojureScript output to bytecode, and achieve *much faster startup - > around 150ms on device*. This is well within the target performance > range, and is fast enough to eliminate any noticeable UI lag. > > One hurdle I ran into is the 64k method size limit for Java classes. Since > jsc compiles all .js files to a single method in a Java class, compiling > cljs/core.js caused errors when compiling to bytecode. I was able to get > around this by splitting the JS files in half during the build process > until they were small enough to compile. *I have since implemented some > optimizations which bring the startup overhead of ClojureScript down to < > 100 ms.* > > > *Pure ClojureScript Android Applications* > > Since I am precompiling the ClojureScript sources, I can also generate > Java classes using ClojureScript macros. Here is an example of an Android > Activity written in ClojureScript. This activity is compiled to Java in a > similar manner to Clojure's gen-class mechanism: > > (ns cljs-hello.core > (:require-macros [lambdroid.compile :refer [java-class]])) > > (java-class > {:name "io.lambdroid.MyActivity" > :extends android.app.Activity}) > > (defn ^:override onCreate [this ^android.os.Bundle state] > (.onCreate this state) > (.setContentView this io.lambdroid.R.layout/activity_hello_world) > (.setText (.findViewById this io.lambdroid.R.id/message > <http://io.lambdroid.r.id/message>) > "Hello From ClojureScript")) > > > Note that this generated activity class is created by Android directly and > has full access to Android asset bundles, so users of this library *will > not need to write any Java whatsoever* . > > > *Next Steps* > > There are a few things I still need to do before releasing code: > > > - Extract build logic into Gradle plugin - it is currently just some > build scripts in an example app. > - Build an Android REPL that can run in the context of the current > activity > - Incremental builds (cljs compile time is currently slow) > > > Once these are finished, I plan to release Lambdroid under a permissive > license. > > > *ClojureScript JVM Applications?* > > As Uday and Mike have alluded, this appriach could potentially be used to > run applications on the JVM as well. This would be ideal for CLI > applications and development. However, due to the many differences between > CLJS and Clojure[4], I think this might be difficult to write the necessary > shims to get something like Leiningen running on Clojurescript. Also, I > think Nashorn would be a more suitable runtime for JVM applications. I’d > love to have someone with more experience weigh in on this possibility! > > Cheers, > Sam > > [1] > http://nicholaskariniemi.github.io/2014/03/12/clojure-android-startup-benchmarks.html > [2] > http://mail.openjdk.java.net/pipermail/nashorn-dev/2013-January/000240.html > [3] > https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino/JavaScript_Compiler > [4] https://github.com/clojure/clojurescript/wiki/Differences-from-Clojure > > > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.