Hey all,
For the last couple of weekends I've been working on a Proof of Concept
JavaScript implementation of Proton.
The approach that I've taken is (I think) quite interesting/unusual but
it's an approach that offers a high level of synergy with
implementations for other languages that are essentially bindings to
proton-c.
The "magic elixir" in this is the downright amazing emscripten
https://github.com/kripken/emscripten/wiki which (believe it or not) is
essentially a cross-compiler that can compile C/C++ to JavaScript.
Moreover the JavaScript that it compiles to is a particular subset
called asm.js http://asmjs.org/ which can be extremely aggressively
optimised and is subject to a lot of research by Mozilla in particular
(the main emscripten maintainer is actually a Mozilla researcher, though
I believe emscripten is something of a side project).
It's well worth visiting the emscripten page with a modern browser, the
Epic Citadel demo is awesome :-)
So in a nutshell what I've done is to compile proton-c into JavaScript
So I'm underselling it a bit :-) I had to do a fair bit of work to make
it that simple, in particular I had to add/fix a number of emscripten's
library functions (Proton used a few things that weren't implemented)
but the cool thing is that those are now in emscripten for everyone's
benefit.
A really nice thing is that I've not actually had to modify any of the
engine/messenger code at all - one I started to figure out what I was
doing wrong that is :-) all I've really needed to to was to modify
send.c/recv.c so that they behave in a non-blocking manner (you may have
seen my mail at the weekend before I finally figured it out :-))
I've got CMake able to cross-compile in a repeatable fashion so the only
change to any existing Proton stuff that is required is an addition to
the top-level CMakeLists.txt that detects the presence of emscripten and
its dependencies and if present fires off
"add_subdirectory(bindings/javascript)" e.g.
# Build the JavaScript language binding.
# This is somewhat different to the other language bindings in that it
does not use swig. It uses a C/C++ to
# JavaScript cross-compiler called emscripten
(https://github.com/kripken/emscripten). Emscripten takes C/C++
# and "compiles" it into a highly optimisable subset of JavaScript
called asm.js (http://asmjs.org/) that can
# be aggressively optimised and run at near-native speed (usually
between 1.5 to 10 times slower than native C/C++).
option("BUILD_JAVASCRIPT" "Build JavaScript language binding" ON)
if (BUILD_JAVASCRIPT)
# First check that Node.js is installed as that is needed by emscripten.
find_program(NODE node)
if (NOT NODE)
message(STATUS "Node.js (http://nodejs.org) is not installed: can't
build JavaScript binding")
else (NOT NODE)
# Check that the emscripten C/C++ to JavaScript cross-compiler is
installed.
find_program(EMCC emcc)
if (NOT EMCC)
message(STATUS "Emscripten
(https://github.com/kripken/emscripten) is not installed: can't build
JavaScript binding")
else (NOT EMCC)
add_subdirectory(bindings/javascript)
endif (NOT EMCC)
endif (NOT NODE)
endif (BUILD_JAVASCRIPT)
So the main purpose of this mail is to give a heads up of it and to ask
if it'd be OK to start commiting it and give others some visibility of it.
At this stage it's something of a Proof of Concept, in particular:
* I haven't exported any actual JavaScript bindings so although it's
JavaScript actual JavaScript clients would find it awkward to call the
API as yet.
* As alluded above and at the weekend the demo code I've got calling
messenger isn't especially elegant, I think I know how to get things
behaving more asynchronously, but haven't tried it yet (and my hunch may
be wrong).
* Transport is entirely over WebSockets :-) so I've actually got send
and recv running on Node.js (and also send on a browser) but it'd be
useful to have them communicate via TCP sockets too - though that'd need
a proxy.
* I still (perhaps amusingly given this) don't know that much about
Proton, so I've only really got send and recv to play with I'm not
really sure where there may be other messenger examples to exercise it a
bit better (in particular message type interoperability would be good to
test). I'd be grateful for pointers - is the object.c test the best
place to look for this? And I couldn't see any tests for the "tracker"
capabilities??
* In case it wasn't clear from the WebSockets it'll only work in a
relatively modern browser at the moment both for the WebSocket stuff and
for the fact that it relies on ArrayBuffers (though there's an
emscripten compile option to allow the use of native JavaScript Arrays
instead)
Finally it's probably worth pointing out some pros and cons for this
approach to creating a JavaScript Proton
Pro:
* It's using the existing proton-c code base with the posix driver.c
completely unchanged (with the simple test I've done to date) so from a
broad maintenance/"Total cost of Ownership" perspective it means
essentially very little extra maintenance costs.
* It follows the same "pattern" as Python/Perl/PHP/Ruby/Java JNI albeit
it's cross-compiled rather than a pure binding.
* It should be somewhat faster than "handwritten" JavaScript. This might
seem counter-intuitive but it's worth looking at the emscripten/asm.js
documentation. From my own experience I've ported zlib to JavaScript for
another project I'm working on and inflate was *significantly* faster
than the literal port of tinflate that I had previously used - and that
was on a relatively old Firefox without asm.js optimisations.
Con:
* The compiled code is likely to be somewhat larger than hand written
JavaScript. I haven't done an optimised & minified build yet so I can't
say for sure how big it will actually be. The unoptimised
send.js/recv.js are 1.5MB each so at a guess they'll probably come out
at arounf the ~500K mark (though they should also gzip quite well).
* The compiled code isn't necessarily hugely readable. It's "OK" when
not optimised but.... (to be fair I used it to figure out how to get the
missing library calls working so it's not *totally* impenetrable :-))
I hope that this is something that'll be useful/interesting please do
let me know if you're all happy for me to get it kicked off into the
Proton code base.
Best regards,
Frase
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@qpid.apache.org
For additional commands, e-mail: users-h...@qpid.apache.org