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.

Reply via email to