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

Reply via email to