ExternalInterface is the API provided by Flash to communicate with its hosting environment. For my case, it is the browsers hosting the Flash “movie”. I noticed different performance behavior on each browser. This is my attempt to measure performance penalty caused by each browser.

Here’s the software versions:

Flash plugin version: 10,0,32,18

Chrome 4.1.249
Firefox 3.6.3
IE 8.0

How did I measure

1. I call Been.FComm.send() function in Javascript and timestamp (Tjs1) it. This JS function calls the send() in the Flash.

2. In the Flash application I timestamp (Tf1) send() function call.

3. In the Flash application I also timestamp (Tf2) handleData() and call been_fcomm_handle JS function.

4. Then I timestamp (Tjs2) been_fcomm_handle() in Javascript.

Flash application is written in Flex. It sends a data over a TCP socket and reads the response back. As all functions, send() and handleData() functions in my application also has a debug() call — which includes a timestamp.

Here’s how I implemented measurement in Flash:

private function debug(str:String):void
{
	var date:Date = new Date();
	output.appendText(date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds() + "." + date.getMilliseconds() + ": " + str);
}

private function handleData(event:ProgressEvent):void
{
	var data:String = m_socket.readUTF();
	debug("handleData"+data+"\n");
	ExternalInterface.call("been_fcomm_handle", data);
}

private function send (value:String):void
{
	debug("sending "+value+"\n");
	m_socket.writeUTF(value);
	m_socket.flush();
}

So that I can measure how long Flash thinks it takes my server to give a response.

On the other hand, I also measure the timings in JS layer. Here’s the related code pieces — simplified to death to only contain relevant codes.

Here’s how I implemented measurement in Javascript:

Been.Debug = new function() {
    this.info = function(m) {
        log(date.toLocaleTimeString() + "." + date.getUTCMilliseconds() + ": " + m);
    };
};

Been.FComm = new function() {
    this.handle = function(msg) {
        Been.Debug.info("Been.FComm.Handle: " + msg);
    }

    this.send = function(data) {
        Been.Debug.info("Been.FComm.send: " + data);
        Been.Utils.getFlashMovieObject("FlashComm").send(data);
    }
    /* rest of the implementation */
};

Results

Here are the results samples.

Chrome

Avarage Flash request/response: 8.3ms
Avarage JS request/response: 161ms
Flash JS communication (marshaling) overhead: 161 - 8.3 = 152.7ms

Flash output
---------------------------------------------------------------------------------------
20:34:20.731: handleData{"Status":"FAILED","Error":"Internal server error.","ErrorNo":500}
20:34:20.719: sending {asf}
20:34:19.519: handleData{"Status":"FAILED","Error":"Internal server error.","ErrorNo":500}
20:34:19.513: sending {asf}
20:34:9.713: handleData{"Status":"FAILED","Error":"Internal server error.","ErrorNo":500}
20:34:9.706: sending {asf}

Javascript output
---------------------------------------------------------------------------------------
20:34:20.990: Been.FComm.Handle: {"Status":"FAILED","Error":"Internal server error.","ErrorNo":500}
20:34:20.720: Been.FComm.send: {asf}
20:34:19.710: Been.FComm.Handle: {"Status":"FAILED","Error":"Internal server error.","ErrorNo":500}
20:34:19.512: Been.FComm.send: {asf}
20:34:09.718: Been.FComm.Handle: {"Status":"FAILED","Error":"Internal server error.","ErrorNo":500}
20:34:09.702: Been.FComm.send: {asf}
Firefox

Avarage Flash request/response: 76ms
Avarage JS request/response: 77.6ms
Flash JS communication (marshaling) overhead: 77.6 - 76 = 1.6ms

Flash output
---------------------------------------------------------------------------------------
20:35:55.385: handleData{"Status":"FAILED","Error":"Internal server error.","ErrorNo":500}
20:35:55.276: sending {asf}
20:35:54.582: handleData{"Status":"FAILED","Error":"Internal server error.","ErrorNo":500}
20:35:54.506: sending {asf}
20:35:53.687: handleData{"Status":"FAILED","Error":"Internal server error.","ErrorNo":500}
20:35:53.644: sending {asf}

Javascript output
---------------------------------------------------------------------------------------
20:35:55.414: Been.FComm.Handle: {"Status":"FAILED","Error":"Internal server error.","ErrorNo":500}
20:35:55.303: Been.FComm.send: {asf}
20:35:54.610: Been.FComm.Handle: {"Status":"FAILED","Error":"Internal server error.","ErrorNo":500}
20:35:54.533: Been.FComm.send: {asf}
20:35:53.715: Been.FComm.Handle: {"Status":"FAILED","Error":"Internal server error.","ErrorNo":500}
20:35:53.670: Been.FComm.send: {asf}
IE

Avarage Flash request/response: 5.3ms
Avarage JS request/response: 7.6ms
Flash JS communication (marshaling) overhead:  7.6 - 5.3 = 1.3ms

Flash output
---------------------------------------------------------------------------------------
20:36:51.166: handleData{"Status":"FAILED","Error":"Internal server error.","ErrorNo":500}
20:36:51.162: sending {asf}
20:36:48.211: handleData{"Status":"FAILED","Error":"Internal server error.","ErrorNo":500}
20:36:48.207: sending {asf}
20:36:47.467: handleData{"Status":"FAILED","Error":"Internal server error.","ErrorNo":500}
20:36:47.459: sending {asf}

Javascript output
---------------------------------------------------------------------------------------
20:36:51.166: Been.FComm.Handle: {"Status":"FAILED","Error":"Internal server error.","ErrorNo":500}
20:36:51.161: Been.FComm.send: {asf}
20:36:48.211: Been.FComm.Handle: {"Status":"FAILED","Error":"Internal server error.","ErrorNo":500}
20:36:48.206: Been.FComm.send: {asf}
20:36:47.469: Been.FComm.Handle: {"Status":"FAILED","Error":"Internal server error.","ErrorNo":500}
20:36:47.456: Been.FComm.send: {asf}

Summary

Browser Flash – JS communication overhead (ms)
Chrome 152.7
IE 1.3
FF 1.6

It looks like Chrome suffers from the most significant overhead, while IE and FF could be considered on a par.