Frase,
This looks really interesting. Can you provide any details about the
WebSockets encapsulation (i.e. how WS messages and frames are used)?
Thanks,
-Ted
On 11/19/2013 02:56 PM, Fraser Adams wrote:
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
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@qpid.apache.org
For additional commands, e-mail: users-h...@qpid.apache.org