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

Reply via email to