On Thu, Apr 28, 2016 at 5:09 PM, Xavier de Gaye <[email protected]> wrote:
> On 04/28/2016 03:01 AM, Russell Keith-Magee wrote: > > (Apologies for the personal repost - I forgot to reply-all on the first > attempt) > > > > Hi Xavier, > > > > Great stuff! > > > > I’ve got a question about your experience integrating with the native > Android platform APIs. > > > > Getting CPython compiled as a native binary library is a huge step, but > my experience has been that bridging between binary libraries and the > Java/Dalvik APIs is a painful process - JNI *exists*, but > > it’s *really* slow, and has some pretty harsh limitations (like the > kernel-imposed JNI reference count limit). > > > > For some applications, this won’t matter - for example, if you’re > treating the android device as a low power server, something that is > terminal only isn’t a problem. However, if you want to write a > > native app, then you need to be able to create an Activity, with a View, > put a Button on it, and a Layout, and so on. Have you done any exploration > of the binding to these native APIs? > > > A first-class citizen java application embeds python using JNI. The > embedded > python accesses the android API by importing and invoking methods of an > android.py module. The android.py module maps those API requests to json > RPC > calls that are sent to another java application so that they may be > processed > and their results returned. This is the design of Scripting Layer for > Android > (SL4A) [1], a languishing project. > Sure. I’m aware of SL4A. It struck me as a neat hack, but not an especially viable approach in practice - certainly not something suitable for an app that you’re expecting to use for wide consumer adoption. > IMHO you should define what 'slow' means, slow for a gaming application, > for > tracking the smartphone accelerometer or for a pyephem based application > that > brings the ephemeresis of stars and planets at your finger tip :) > My use case was a fairly simple native application, a couple of inputs and a button. I took a Python implementation of the Cassowary widget layout algorithm - the same one that iPhones use natively - and tried to use that layout algorithm for widgets on the Android view - and it was almost unusably slow. “Slow” meant ~5 second startup time for a “hello world” app, and observable lags in widget redraw on device rotation. If I was getting that with only a couple of widgets on the screen, I didn’t want to think what it would be like with a complex UI. My diagnosis of the situation found two sources of slowdown: 1) The Android kernel imposes a hard limit on the number of JNI references that a single application can hold, and that limit is impractically low. I forget the exact number but the limit is something like 1000 - but a full rollout of the classes involved in starting Hello World involves 4500 JNI references. So - you end up having to do on-demand JNI lookups, and aggressive LRU caching, all of which slows down actual use - you can’t just write off the problem as a startup cost. 2) The JNI marshalling layer itself was about an order of magnitude slower than it is on a desktop JNI bridge. Getting a JNI reference, making a call across the JNI bridge - all these operations took *much* longer than the comparable operations on a desktop machine, even when you allow for the differences in CPU speed. FWIW - I was working on embedded CPython about 18 months ago, and gave up because these problems didn’t seem solvable. I was hoping you might have found a different way into the native capabilities of the Android platform. My conclusion is that Android *REALLY* wants you to be writing Java, not using JNI. As a result, I gave up on the JNI approach, and took a different tack. VOC [1] is a transpiler - but not a source code transpiler. It takes CPython bytecode as input (instructions for a stack-based virtual machine), and converts that bytecode to Java classfiles (bytecode for different stack-based virtual machine). That way, you can take Python code [2], compile it *directly* to equivalent Java class files, where it runs completely natively [3], with fairly acceptable performance. When the JVM throws a stack trace, it references the *Python* source code line number. To be clear - this isn’t source code transpilation - it’s at the bytecode level.. It’s also different to Jython, in that it doesn’t carry the overhead of an interpreter to the runtime - you’re shipping precompiled, ready-to-run Java bytecode. The downside is that there isn’t a REPL or an exec()/eval() call - but for my use case (writing apps for end users), that’s a limitation I can live with. [1] https://github.com/pybee/voc [2] https://gist.github.com/freakboy3742/3c6b74e8506d47d9bd97 [3] https://twitter.com/PyBeeWare/status/683258762816192513 Yours Russ Magee %-)
_______________________________________________ Mobile-sig mailing list [email protected] https://mail.python.org/mailman/listinfo/mobile-sig
