How much Avian is alive? How it is suitable as scripting language?

170 views
Skip to first unread message

funny....@gmail.com

unread,
Dec 11, 2016, 11:36:19 AM12/11/16
to Avian
Hello,

Looks like development is reduced in last two years.
Is ReadyTalk still using avian a lot? Is it interested in vm development?
What future AvianVM has?

Another question:
- currently project I'm involved in uses LuaJIT as a scripting language.
But there is a lot of frustration with its behavior (and future).
- once project tried to embed V8 as well, but V8 had large overhead to
pass native/vm barrier (ie invoking javascript methods from native core
and vise-versa were expensive).

How expensive call from native code to Java code? How expensive
call of native code from Java code? And passing objects/values to and from VM?

I know, these questions are hard to answer.
I will be grateful for any suggestions.

With regards,
Yura.

Joshua Warner

unread,
Dec 11, 2016, 2:06:46 PM12/11/16
to Avian
You're right, development has slowed in recent years.

ReadyTalk still depends on Avian for production clients, but we haven't had cause to update Avian for our purposes for a while.  It's pretty stable and feature-complete from that perspective.

Because we haven't had many required changes, Avian has slowly been slipping into maintenance-only mode.  For the last couple years, it's been almost solely community-driven features and bug fixes.  IMO, I think the ship has sailed for non-android, client-side Java; so it's just as well.  I think it's unlikely at this point that we'll see a big resurgence in Avian development.

From what little I know about LuaJIT and V8, I'm a little surprised your seeing larger FFI (foreign function interface) overhead on V8; I would have thought Google would put a lot of effort into minimizing that.

I haven't benchmarked it, but I wouldn't expect Avian to be significantly better than either LuaJIT or V8.  Anytime you have a dynamic checking involved, things slow down substantially, and I have yet to see an FFI system for a dynamic or interpreted language that doesn't do dynamic checking.  I'm not even sure it's possible.

I find it interesting that a lot of projects have been moving away from embedding scripting languages as such: Unreal Engine 4 went to a c++-based scripting model, and Unity 3D has been moving towards a fully-compiled model with il2cpp.  Also, Google's load-balancer is just a Go library, where all the logic that you'd typically use configuration or scripting for is just Go code that links against said library.  Some notable modern editors are eschewing embedded scripting languages for IPC calls to arbitrary other systems.

Existing projects aside, I think the legitimate use-cases for embedded scripting languages are rapidly diminishing.  Even javascript these days is written as if it's using the browser as a library.

I think it comes down to two things:
* Incredibly light-weight systems
* Extreme platform independence in large-scale systems

The former is fragile since people are always pushing the state of the art.  The latter is good for crossing strong organizational boundaries, but is a big hinderance if it's not necessary.  It's great if you're a browser vendor or a PaaS offering, but I think below that scale, you're just playing with fire.

Libraries are composable, but frameworks and embedded scripting languages are much less so.

Sorry for the rant.  TL;DR: I don't think there's a really good answer in this space right now.

-Joshua

--
You received this message because you are subscribed to the Google Groups "Avian" group.
To unsubscribe from this group and stop receiving emails from it, send an email to avian+un...@googlegroups.com.
To post to this group, send email to av...@googlegroups.com.
Visit this group at https://groups.google.com/group/avian.
For more options, visit https://groups.google.com/d/optout.

Joel Dice .

unread,
Dec 12, 2016, 1:14:46 PM12/12/16
to Avian
On Sun, Dec 11, 2016 at 6:32 AM, <funny....@gmail.com> wrote:
> How expensive call from native code to Java code?

That's fairly expensive, since it involves dynamic argument marshaling
and extra bookkeeping to handle exception unwinding correctly.

> How expensive call of native code from Java code?

That's less expensive than native-to-Java, and better-optimized.
Avian also has its own, VM-specific native interface which bypasses
all of the type safety and GC safety precautions that normal JNI calls
entail (and is therefore very dangerous to use if you're not careful).

> And passing objects/values to and from VM?

This depends on what kind of objects and values you're passing around.
The most efficient cases are primitives (e.g. ints, longs, doubles,
etc) and primitive arrays (e.g. byte arrays) when using
GetPrimitiveArrayCritical. Object field and method accesses will be
more expensive since they involve runtime type checks and dispatches.

Generally speaking, you should avoid crossing between Java and native
code frequently in performance-sensitive code.

Also, remember that Avian only understands Java bytecode. If your
scripts are delivered as Java source code, they'll need to be compiled
to bytecode before Avian can execute them.

Terasgr

unread,
Dec 13, 2016, 3:22:50 AM12/13/16
to Avian


Τη Δευτέρα, 12 Δεκεμβρίου 2016 - 8:14:46 μ.μ. UTC+2, ο χρήστης Joel Dice έγραψε:
Avian also has its own, VM-specific native interface which bypasses
all of the type safety and GC safety precautions that normal JNI calls
entail (and is therefore very dangerous to use if you're not careful).


Is there a documentation about this feature?

Joel Dice .

unread,
Dec 13, 2016, 12:21:11 PM12/13/16
to Avian
Sorry, no, but you can see examples in src/builtin.cpp,
src/classpath-openjdk.cpp, etc.. Every function starting with
"Avian_" uses the "fast" calling convention. For example:

extern "C" AVIAN_EXPORT void JNICALL
Avian_sun_misc_Unsafe_putByteVolatile(Thread*, object, uintptr_t* arguments)
{
object o = reinterpret_cast<object>(arguments[1]);
int64_t offset;
memcpy(&offset, arguments + 2, 8);
int8_t value = arguments[4];

storeStoreMemoryBarrier();
fieldAtOffset<int8_t>(o, offset) = value;
storeLoadMemoryBarrier();
}

Every function using this convention takes three arguments (Thread*
thread, object method, uintptr_t* javaArguments) and returns either
void or int64_t. The `Thread* thread` parameter is basically a
JNIEnv* pointer, but one that also exposes the VM internals. The
`object method` parameter is a avian.VMMethod reference corresponding
to the native method being invoked. The `uintptr_t* javaArguments`
parameter is an array of primitives and/or references which are the
arguments passed from Java code.

In the example above, the Java method signature is
sun.misc.Unsafe.putByteVolatile(Object target, long offset, byte
value). Note that long values always occupy two elements of the
arguments array, even on 64-bit platforms.

Note that functions using this convention are assumed not to block for
significant amounts of time since that will prevent garbage collection
and eventually halt all threads. Also, these functions cannot call
back into the VM without using the PROTECT macro with all object
references to tell the VM about GC roots on the stack. If you forget
to do this, your program will crash unpredictably.
Reply all
Reply to author
Forward
0 new messages