I am creating a Firefox extension that allows using Standard ML (SML) as a client-side programming language in Firefox. The way it works is the following:
- The extension launches a PolyML process (SML compiler with a top-level interactive shell).
- A socket communication is then established between the extension and the PolyML process.
- SML code is read from the webpage and is sent via the sockets to the PolyML process for evaluation.
- That code may then use a library that I provide, for working with the DOM.
Here is how the DOM library is implemented:
- Say someone executes an SML function DOM.getElementById
- This request is forwarded via the sockets to the extension, where the extension executes the JavaScript function getElementById on the page and sends the result back to the PolyML process via the sockets.
My question is, in theory, what limits in terms of performance should I be expecting to have here, when it comes to the socket communication?
I did some very approximate profiling and it seems that using this interface between the extension and PolyML, I can approximately send 2500 messages/second, of an average size of 70 bytes/message.
To put this in more context, say I want to draw some animations in the browser using the Canvas element. If I want to achieve 20fps, that means I need to draw every frame in 0.05 seconds, which means I can only send around 125 messages per frame. Those messages correspond to JavaScript function calls. For example, the code below draws a path and is making 9 JavaScript function calls, that correspond to 9 messages in the socket communication.
val _ = Canvas.beginPath context; val _ = Canvas.setFillStyle context fillColor; val _ = Canvas.setStrokeStyle context fillColor; val _ = Canvas.setLineWidth context size; val _ = Canvas.moveTo context posx posy; val _ = Canvas.lineTo context posx_new posy_new; val _ = Canvas.stroke context; val _ = Canvas.arc context posx_new posy_new (size/2.0) 0.0 6.28 true; val _ = Canvas.fill context;
JavaScript, obviously, has a much better performance, I would imagine that you could make thousands (hundreds) of times of more Canvas/DOM function calls in those 0.05 seconds, for drawing a frame.
So, I guess my question is, do you have any experience with using socket communication for very rapid message interchange. I would like to know whether 2500 small messages / second (in this case, corresponding to 150 kbytes/second) seems about right or might I be doing something very wrong.
For example, one suspicion is that the socket implementation in firefox (in particular using it via the JavaScript interface https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIServerSocket) is not very good for this kind of rapid interaction. For example, the reading from the socket is done via an event loop mechanism. That is I rely on Firefox.. to notify me about the availability of incoming socket messages and sometimes there is a large (e.g. 250ms) delay between sending the message and receiving it (though that seems to be happening only when firefox is busy with doing other things, and I'm more interested in the ..theoretical.. limits of the socket communication)
Any ideas, any thoughts, any flaws that you see? Do you think using other IPC mechanisms would be better, e.g. pipes, implementing my communication from C++ XPCOM component, rather than from JavaScript, foreign function interface to C (that both JavaScript and PolyML have)?
(The project is located at https://assembla.com/wiki/show/polymlext if anyone's interested)