Details

    • Type: Improvement Improvement
    • Status: Resolved
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 2.2.0
    • Component/s: Android
    • Labels:

      Description

      Doing many native callbacks (such as writing files) has a significant overhead.

      Trigger.io's native bridge is more than 5 times faster than Cordova (on Android). http://trigger.io/cross-platform-application-development-blog/wp-content/uploads/2012/02/chart_1-21.png

      I'd love to see similar performance stats in Cordova.

        Issue Links

          Activity

          Hide
          Patrick Mueller added a comment -

          We probably should enable, optionally, and not by default being able to use the WebView.addJavascriptInterface() API, instead of the current bridge.

          It seems quite possible that this enablement would entail making a decision at runtime which bridge to use, since the addJavascriptInterface() bridge will cause a trap on some simulators, but work on devices running the same major/minor version of Android.

          Having said that, most of these bridges are potentially huge bottlenecks anyway, across many platforms. It might also be useful to think of some alternatives - like batching requests, or something. It would might also be useful to try to lobby the platform developers to give us some alternatives, like a postMessage() type of interface.

          Show
          Patrick Mueller added a comment - We probably should enable, optionally , and not by default being able to use the WebView.addJavascriptInterface() API, instead of the current bridge. It seems quite possible that this enablement would entail making a decision at runtime which bridge to use, since the addJavascriptInterface() bridge will cause a trap on some simulators, but work on devices running the same major/minor version of Android. Having said that, most of these bridges are potentially huge bottlenecks anyway, across many platforms. It might also be useful to think of some alternatives - like batching requests, or something. It would might also be useful to try to lobby the platform developers to give us some alternatives, like a postMessage() type of interface.
          Hide
          Joe Bowser added a comment - - edited

          I'd love to see stats that are independent and are not subject to a third party who won't open source their code. It's in trigger.io's interest to promote these numbers, since AFAIK there's no way that we can verify what they are saying.

          Show
          Joe Bowser added a comment - - edited I'd love to see stats that are independent and are not subject to a third party who won't open source their code. It's in trigger.io's interest to promote these numbers, since AFAIK there's no way that we can verify what they are saying.
          Hide
          Lee Crossley added a comment -

          @Patrick - I agree that batching requests (such as file writes) would be faster, as you're minimising the native callbacks but that is just sticking duck-tape on it and could lead to other issues. I'm experiencing a 300+ms delay in small file writes on Android 2.3.5 - it's less than a 10th of that on iOS. Using the WebView.addJavascriptInterface() API (optionally) could be a great idea.

          @Joe - Yes, seeing the source and having an independent party do some testing would be interesting, I don't think that's going to happen with their commercial modelling My point wasn't really that there's something faster, it's more than I'm experiencing poor performance on Android devices, especially with earlier Android SDK versions (I'm experiencing a 300+ms delay in small file writes on Android 2.3.5). It's less than a 10th of that on iOS and what I'm asking is to see similar performance cross platform.

          Show
          Lee Crossley added a comment - @Patrick - I agree that batching requests (such as file writes) would be faster, as you're minimising the native callbacks but that is just sticking duck-tape on it and could lead to other issues. I'm experiencing a 300+ms delay in small file writes on Android 2.3.5 - it's less than a 10th of that on iOS. Using the WebView.addJavascriptInterface() API (optionally) could be a great idea. @Joe - Yes, seeing the source and having an independent party do some testing would be interesting, I don't think that's going to happen with their commercial modelling My point wasn't really that there's something faster, it's more than I'm experiencing poor performance on Android devices, especially with earlier Android SDK versions (I'm experiencing a 300+ms delay in small file writes on Android 2.3.5). It's less than a 10th of that on iOS and what I'm asking is to see similar performance cross platform.
          Hide
          Joe Bowser added a comment -

          I don't think that switching to addJavascriptInterface itself will work, since we'll still have to use polling to get the async response. The only difference is that this will be cleaner. Java classes added to the application are synchronous by default, and the only way that Android can call Javascript on its own is by using WebView.loadURL, which calls the old WebKit C method stringByEvaluatingJavascriptString, but this also interrupts the UI thread. We work around this by adding a callback server and using an XHR to listen to the server for callbacks. In the case that a server connection can't get established, we use polling.

          So, it's not just about using addJavascriptInterface, although I would love to go back to using it for input, because it would make the code a LOT cleaner.

          Show
          Joe Bowser added a comment - I don't think that switching to addJavascriptInterface itself will work, since we'll still have to use polling to get the async response. The only difference is that this will be cleaner. Java classes added to the application are synchronous by default, and the only way that Android can call Javascript on its own is by using WebView.loadURL, which calls the old WebKit C method stringByEvaluatingJavascriptString, but this also interrupts the UI thread. We work around this by adding a callback server and using an XHR to listen to the server for callbacks. In the case that a server connection can't get established, we use polling. So, it's not just about using addJavascriptInterface, although I would love to go back to using it for input, because it would make the code a LOT cleaner.
          Hide
          Patrick Mueller added a comment -

          ya, forgot about the stringByEvaluatingJavascriptString() issues.

          really need to get Google to fix this ())(& up.

          Show
          Patrick Mueller added a comment - ya, forgot about the stringByEvaluatingJavascriptString() issues. really need to get Google to fix this () ) (& up.
          Hide
          Joe Bowser added a comment -

          This won't get fixed for 2.0 sadly, we need to send this to the future.

          Show
          Joe Bowser added a comment - This won't get fixed for 2.0 sadly, we need to send this to the future.
          Hide
          Andrew Grieve added a comment -

          Relevant mailing-list thread going on: http://markmail.org/message/jvl6kt7dszp3sgr3

          Show
          Andrew Grieve added a comment - Relevant mailing-list thread going on: http://markmail.org/message/jvl6kt7dszp3sgr3
          Hide
          Andrew Grieve added a comment -

          I'm going to work on implementing the various bridge modes so that they can be easily toggled between and also write an echo plugin based benchmark (iOS now has one already)

          Show
          Andrew Grieve added a comment - I'm going to work on implementing the various bridge modes so that they can be easily toggled between and also write an echo plugin based benchmark (iOS now has one already)
          Hide
          Brian LeRoux added a comment -

          @andrew would be good to factor the various bridge impls into strategies that we could dynamically load based on the device (falling back to the current solution if we're not confident of the device).

          Show
          Brian LeRoux added a comment - @andrew would be good to factor the various bridge impls into strategies that we could dynamically load based on the device (falling back to the current solution if we're not confident of the device).
          Hide
          Andrew Grieve added a comment -

          I've checked in the first round of changes for this. Modes can be tested in the mobile-spec exec() benchmark.

          jsToNativeModes =

          { PROMPT: 0, JS_OBJECT: 1, LOCATION_CHANGE: 2 // Not yet implemented }

          ,
          nativeToJsModes =

          { // Polls for messages using the prompt() bridge. POLLING: 0, // Does an XHR to a local server, which will send back messages. This is // broken on ICS when a proxy server is configured. HANGING_GET: 1, // For LOAD_URL to be viable, it would need to have a work-around for // the bug where the soft-keyboard gets dismissed when a message is sent. LOAD_URL: 2, // For the ONLINE_EVENT to be viable, it would need to intercept all event // listeners (both through addEventListener and window.ononline) as well // as set the navigator property itself. ONLINE_EVENT: 3, // Uses reflection to access private APIs of the WebView that can send JS // to be executed. // Requires Android 3.2.4 or above. PRIVATE_API: 4 }

          ;

          -I've not implemented the any keyboard work-arounds for LOAD_URL
          -I've not added a workaround for hiding online/offline events from changing
          -JS_OBJECT probably needs a better enable/disable detection. Right now it's disabled only for the 2.3 emulator instead of checking for JSC (via http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-andro)

          Some initial benchmark results from my Galaxy Nexus (echos per second, bigger is better, payload size=500 bytes):

          Sync JS->Native:
          PROMPT: 570
          JS_OBJECT: 800

          Using JS_OBJECT for JS->Native and async Native->Response:
          Native->JS POLLING+PROMPT: 100
          Native->JS HANGING_GET: 75-90
          Native->JS LOAD_URL: 160
          Native->JS ONLINE_EVENT+PROMPT: 200-270
          Native->JS PRIVATE_API: 340

          ONLINE_EVENT being faster than LOAD_URL surprised me. Especially since it can be made even a bit faster if it uses JS_OBJECT to retrieve the message instead of PROMPT.

          Still to do:
          Implement LOCATION_CHANGE JS>Native mode
          -Add detection logic for JS_OBJECT support (this will involve loading a test page to run some JS)
          -Add hiding of ONLINE_EVENTS changes from the app via cordova.addWindowEventHandler() and navigator._defineGetter_('onLine', ...)
          -Make POLLING and ONLINE_EVENT be able to use JS_OBJECT instead of always PROMPT.
          -Make POLLING & HANGING_GET retrieve all pending messages in one call instead of one at a time
          -Add mobile-spec test that ensures all modes work (when expected to)

          Final Steps:
          -Discuss changing the default bridge mode, as well as how to implement fall-back modes.

          Show
          Andrew Grieve added a comment - I've checked in the first round of changes for this. Modes can be tested in the mobile-spec exec() benchmark. jsToNativeModes = { PROMPT: 0, JS_OBJECT: 1, LOCATION_CHANGE: 2 // Not yet implemented } , nativeToJsModes = { // Polls for messages using the prompt() bridge. POLLING: 0, // Does an XHR to a local server, which will send back messages. This is // broken on ICS when a proxy server is configured. HANGING_GET: 1, // For LOAD_URL to be viable, it would need to have a work-around for // the bug where the soft-keyboard gets dismissed when a message is sent. LOAD_URL: 2, // For the ONLINE_EVENT to be viable, it would need to intercept all event // listeners (both through addEventListener and window.ononline) as well // as set the navigator property itself. ONLINE_EVENT: 3, // Uses reflection to access private APIs of the WebView that can send JS // to be executed. // Requires Android 3.2.4 or above. PRIVATE_API: 4 } ; -I've not implemented the any keyboard work-arounds for LOAD_URL -I've not added a workaround for hiding online/offline events from changing -JS_OBJECT probably needs a better enable/disable detection. Right now it's disabled only for the 2.3 emulator instead of checking for JSC (via http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-andro ) Some initial benchmark results from my Galaxy Nexus (echos per second, bigger is better, payload size=500 bytes): Sync JS->Native: PROMPT: 570 JS_OBJECT: 800 Using JS_OBJECT for JS->Native and async Native->Response: Native->JS POLLING+PROMPT: 100 Native->JS HANGING_GET: 75-90 Native->JS LOAD_URL: 160 Native->JS ONLINE_EVENT+PROMPT: 200-270 Native->JS PRIVATE_API: 340 ONLINE_EVENT being faster than LOAD_URL surprised me. Especially since it can be made even a bit faster if it uses JS_OBJECT to retrieve the message instead of PROMPT. Still to do: Implement LOCATION_CHANGE JS >Native mode -Add detection logic for JS_OBJECT support (this will involve loading a test page to run some JS) -Add hiding of ONLINE_EVENTS changes from the app via cordova.addWindowEventHandler() and navigator._ defineGetter _('onLine', ...) -Make POLLING and ONLINE_EVENT be able to use JS_OBJECT instead of always PROMPT. -Make POLLING & HANGING_GET retrieve all pending messages in one call instead of one at a time -Add mobile-spec test that ensures all modes work (when expected to) Final Steps: -Discuss changing the default bridge mode, as well as how to implement fall-back modes.
          Hide
          Andrew Grieve added a comment -

          Another approach I'm going to play with: Using onhashchange to send messages native->JS. Supported in 2.2 onward and might mess up the app, but worth testing the performance of.

          Show
          Andrew Grieve added a comment - Another approach I'm going to play with: Using onhashchange to send messages native->JS. Supported in 2.2 onward and might mess up the app, but worth testing the performance of.
          Hide
          Andrew Grieve added a comment -

          Updates:

          • Checked in support for JS->Native via window.location.
          • At first look, it is about 15% slower than prompt.
          • For calls that are async, or that have no return values, it looks to be about 40% faster than prompt (I think because it saves having to have a sync return value)
          • I've disabled it behind a flag for now because I think the security implications of it should be discussed. Could be that a malicious user forms a link that executes a native command.
          • Adding detection for JS_OBJECT
          • I've changed my mind on this, and now think that we should leave the logic as detecting the 2.3 simulator, and hope for the best.
          • My reasoning is that there is no good way to feature-detect this support, other than crashing the app and recording the event. All other ways can have false-positives.
          Show
          Andrew Grieve added a comment - Updates: Checked in support for JS->Native via window.location. At first look, it is about 15% slower than prompt. For calls that are async, or that have no return values, it looks to be about 40% faster than prompt (I think because it saves having to have a sync return value) I've disabled it behind a flag for now because I think the security implications of it should be discussed. Could be that a malicious user forms a link that executes a native command. Adding detection for JS_OBJECT I've changed my mind on this, and now think that we should leave the logic as detecting the 2.3 simulator, and hope for the best. My reasoning is that there is no good way to feature-detect this support, other than crashing the app and recording the event. All other ways can have false-positives.
          Hide
          Andrew Grieve added a comment -

          Also, I'm not going to bother with hash change based communications. Most apps use hash to handle navigation and this would clearly conflict.

          Show
          Andrew Grieve added a comment - Also, I'm not going to bother with hash change based communications. Most apps use hash to handle navigation and this would clearly conflict.
          Hide
          Joe Bowser added a comment -

          @Andrew Where is this currently checked in? Is it already in our master, or is it in a branch that you have? Do you have a link that I can look at?

          Show
          Joe Bowser added a comment - @Andrew Where is this currently checked in? Is it already in our master, or is it in a branch that you have? Do you have a link that I can look at?
          Hide
          Andrew Grieve added a comment -

          What an excellent time to ask for an update! I've got some fresh measurements to share.

          All of the modes are already checked in to the main repo, but I've got several local tweaks & changes (mostly for online events) that I'm holding off merging until 2.1.0 is out the door. You can see them here:

          https://github.com/agrieve/incubator-cordova-js/commits/navigatorconn
          https://github.com/agrieve/incubator-cordova-android/commits/exec

          Timings from today: https://docs.google.com/spreadsheet/ccc?key=0Aq9kFRDB1QGhdEtZZENBMThLSDdRUVJfRUFzVW5LSVE#gid=0

          The updated todo list is:

          • Make the native side set the online state to on/off on start-up just in case it one day doesn't default to ON at start-up.
          • Make poll retrieve all pending messages instead of one-at-a-time.
          • Make poll retrieve a list of callback responses that it can pass to cordova.callbackSuccess/callbackFailure directly (to save on eval() cost)
          • Use a thread-pool in PluginManager instead of spinning up a new thread every time
          • Redo benchmarks

          Updates on my thinking:

          • LOCATION_CHANGE is not faster for the async case (I wasn't thinking straight when I said this), it is faster only for calls that have no return values.
          • Due to the way exec always requires a callback (either win or fail), this never applies!
          • It could be made to work if we faked the success callback from JS and update all platforms to not send the OK from native code. This is not worth the effort.
          • Adding fail-safe logic for PRIVATE_API is probably not worth it, as it currently looks like ONLINE_EVENTS is just as fast (and maybe faster after more optimizing). Let's not use it if there's no big win.
          Show
          Andrew Grieve added a comment - What an excellent time to ask for an update! I've got some fresh measurements to share. All of the modes are already checked in to the main repo, but I've got several local tweaks & changes (mostly for online events) that I'm holding off merging until 2.1.0 is out the door. You can see them here: https://github.com/agrieve/incubator-cordova-js/commits/navigatorconn https://github.com/agrieve/incubator-cordova-android/commits/exec Timings from today: https://docs.google.com/spreadsheet/ccc?key=0Aq9kFRDB1QGhdEtZZENBMThLSDdRUVJfRUFzVW5LSVE#gid=0 The updated todo list is: Make the native side set the online state to on/off on start-up just in case it one day doesn't default to ON at start-up. Make poll retrieve all pending messages instead of one-at-a-time. Make poll retrieve a list of callback responses that it can pass to cordova.callbackSuccess/callbackFailure directly (to save on eval() cost) Use a thread-pool in PluginManager instead of spinning up a new thread every time Redo benchmarks Updates on my thinking: LOCATION_CHANGE is not faster for the async case (I wasn't thinking straight when I said this), it is faster only for calls that have no return values. Due to the way exec always requires a callback (either win or fail), this never applies! It could be made to work if we faked the success callback from JS and update all platforms to not send the OK from native code. This is not worth the effort. Adding fail-safe logic for PRIVATE_API is probably not worth it, as it currently looks like ONLINE_EVENTS is just as fast (and maybe faster after more optimizing). Let's not use it if there's no big win.
          Hide
          Andrew Grieve added a comment -

          Two more ideas to pursue:

          • Setting the network state from the background thread instead of using runOnUiThread() (this will cause a warning log message, but should work fine)
          • Removing setTimeouts on the JS side, or change them to postMessage()
          Show
          Andrew Grieve added a comment - Two more ideas to pursue: Setting the network state from the background thread instead of using runOnUiThread() (this will cause a warning log message, but should work fine) Removing setTimeouts on the JS side, or change them to postMessage()
          Hide
          Joe Bowser added a comment -

          @Andrew What is the default bridge with this new code? It appears that we're using polling as the default. I'm fine with this, because this means that there are issues with Android that are now resolved, but I want to know if this was intentional, since this is a change from HANGING_GET being the default.

          IMO HANGING_GET and the Callback Server should be thrown away, since they cause more problems than they solve as far as complexity and memory usage.

          Show
          Joe Bowser added a comment - @Andrew What is the default bridge with this new code? It appears that we're using polling as the default. I'm fine with this, because this means that there are issues with Android that are now resolved, but I want to know if this was intentional, since this is a change from HANGING_GET being the default. IMO HANGING_GET and the Callback Server should be thrown away, since they cause more problems than they solve as far as complexity and memory usage.
          Hide
          Andrew Grieve added a comment -

          Right now, the default bridge is still HANGING_GET, with a fall-back to polling. It's set here:
          https://github.com/agrieve/incubator-cordova-js/blob/10264ba16f74ceeb284219f1a8ce1582892f9d25/lib/android/exec.js#L55

          Definitely looking like there is not future for the callback server. Agree we should just axe it once this is all said and done.

          Show
          Andrew Grieve added a comment - Right now, the default bridge is still HANGING_GET, with a fall-back to polling. It's set here: https://github.com/agrieve/incubator-cordova-js/blob/10264ba16f74ceeb284219f1a8ce1582892f9d25/lib/android/exec.js#L55 Definitely looking like there is not future for the callback server. Agree we should just axe it once this is all said and done.
          Hide
          Andrew Grieve added a comment -

          I'm now finished all of the TODO items I had outlined above and some "final" results!

          Joe - I've updated the two branches with the latest changes, so if you're able to benchmark on other android devices with the latest code changes, that would be awesome!

          The update benchmarks are reflected in the spreadsheet I linked to. But the TLDR:

          Initial vs new bridge speed (calls / second) for synchronous echoes with a 500 character string: 480 vs 1100 == 2.3x improvement
          Initial vs new bridge speed (calls / second) for asynchronous echoes with a 500 character string: 34 vs 835 == 25x improvement

          Show
          Andrew Grieve added a comment - I'm now finished all of the TODO items I had outlined above and some "final" results! Joe - I've updated the two branches with the latest changes, so if you're able to benchmark on other android devices with the latest code changes, that would be awesome! The update benchmarks are reflected in the spreadsheet I linked to. But the TLDR: Initial vs new bridge speed (calls / second) for synchronous echoes with a 500 character string: 480 vs 1100 == 2.3x improvement Initial vs new bridge speed (calls / second) for asynchronous echoes with a 500 character string: 34 vs 835 == 25x improvement
          Hide
          Joe Bowser added a comment -

          OK, Ignore the last one, I didn't update the JS, I'll check them out today.

          Show
          Joe Bowser added a comment - OK, Ignore the last one, I didn't update the JS, I'll check them out today.
          Hide
          Joe Bowser added a comment -

          I'm not noticing the speed-up on the HTC One X. Have the repositories been updated?

          Show
          Joe Bowser added a comment - I'm not noticing the speed-up on the HTC One X. Have the repositories been updated?
          Hide
          Andrew Grieve added a comment -

          Well that would be highly disappointing. Just verified that these both have all the changes:

          https://github.com/agrieve/incubator-cordova-js/commits/navigatorconn
          https://github.com/agrieve/incubator-cordova-android/commits/exec

          Show
          Andrew Grieve added a comment - Well that would be highly disappointing. Just verified that these both have all the changes: https://github.com/agrieve/incubator-cordova-js/commits/navigatorconn https://github.com/agrieve/incubator-cordova-android/commits/exec
          Hide
          Joe Bowser added a comment -

          Here's the numbers that I got across the devices I have on hand here. Are you sure that you have everything committed?

          https://docs.google.com/spreadsheet/ccc?key=0AhShcWAF4JOPdGIxZ1dVWFRTbnJJRXpDbHFDMVZPaVE

          Show
          Joe Bowser added a comment - Here's the numbers that I got across the devices I have on hand here. Are you sure that you have everything committed? https://docs.google.com/spreadsheet/ccc?key=0AhShcWAF4JOPdGIxZ1dVWFRTbnJJRXpDbHFDMVZPaVE
          Hide
          Andrew Grieve added a comment -

          Yep, everything's in there. Your numbers do at least show the same relative speeds (online being the fastest async case). It shouldn't be the case that sync would ever be slower than async though. That makes no sense whatsoever.

          I used the my manual test page to do all of my timings, tomorrow I'll try it with your more automated one and see if the numbers look any different.

          For SYNC and prompt/js_object, no need to test with different Native->JS modes. They won't even come into play.

          Show
          Andrew Grieve added a comment - Yep, everything's in there. Your numbers do at least show the same relative speeds (online being the fastest async case). It shouldn't be the case that sync would ever be slower than async though. That makes no sense whatsoever. I used the my manual test page to do all of my timings, tomorrow I'll try it with your more automated one and see if the numbers look any different. For SYNC and prompt/js_object, no need to test with different Native->JS modes. They won't even come into play.
          Hide
          Andrew Grieve added a comment -

          Other things to sanity check - when benchmarking make sure you don't have a USB connected (adb bridge slows things down).

          I also made sure to launch the app using the "Run" action instead of Eclipse's "Debug" action. Debug vs Release makes a difference on iOS, but I'm not sure if there's a difference for Android apps...

          Show
          Andrew Grieve added a comment - Other things to sanity check - when benchmarking make sure you don't have a USB connected (adb bridge slows things down). I also made sure to launch the app using the "Run" action instead of Eclipse's "Debug" action. Debug vs Release makes a difference on iOS, but I'm not sure if there's a difference for Android apps...
          Hide
          Andrew Grieve added a comment -

          Okay, tried out your jasmine-based tester on my phone and got numbers similar to yours. Biggest difference is that you should set useSetTimeout to false since that is relevant only on iOS where the synchronous call goes from Native->JS (the setTimeout prevents passing JS->Native messages as a return value to this sync native->js call).

          You should also reset the js->native bridge modes in reset() since that does affect how online-events and polling query for messages.

          The prompt js->native one is way off. The logs suggest the test is being started before onPageFinished, so that's likely the cause.

          The HANGING_GET mode is also off. I added stack trace printing to popAndEncode(), and it appears that it is using PROMPT to send the message back to JS. I'm not exactly sure why yet, but it seems to be hitting an optimization I added where any exec() will fetch down pending native->js message from prior calls.

          Last thing - Found this line: "Should work with load_url (not on emulator)". Not sure why it wouldn't work on the emulator though... Did you mean that to be for JS_OBJECT and the 2.3 emulator?

          Show
          Andrew Grieve added a comment - Okay, tried out your jasmine-based tester on my phone and got numbers similar to yours. Biggest difference is that you should set useSetTimeout to false since that is relevant only on iOS where the synchronous call goes from Native->JS (the setTimeout prevents passing JS->Native messages as a return value to this sync native->js call). You should also reset the js->native bridge modes in reset() since that does affect how online-events and polling query for messages. The prompt js->native one is way off. The logs suggest the test is being started before onPageFinished, so that's likely the cause. The HANGING_GET mode is also off. I added stack trace printing to popAndEncode(), and it appears that it is using PROMPT to send the message back to JS. I'm not exactly sure why yet, but it seems to be hitting an optimization I added where any exec() will fetch down pending native->js message from prior calls. Last thing - Found this line: "Should work with load_url (not on emulator)". Not sure why it wouldn't work on the emulator though... Did you mean that to be for JS_OBJECT and the 2.3 emulator?
          Hide
          Andrew Grieve added a comment -

          After a bike ride and a shower, I have a good guess as to what's going on

          I think it's a race condition.

          #Thread 1 - exec called and starts echo on thread 2
          #Thread 2 - thread runs and pushes the result on the queue
          #Thread 1 - returns from exec to find message on the queue
          #Thread 1 - returns the result to the prompt() call.

          I'm not really sure how to easily add a flag to avoid this optimization given the current structure of the code. Maybe have pluginManager.exec return a boolean indicating async vs sync. Or just don't worry about it

          Show
          Andrew Grieve added a comment - After a bike ride and a shower, I have a good guess as to what's going on I think it's a race condition. #Thread 1 - exec called and starts echo on thread 2 #Thread 2 - thread runs and pushes the result on the queue #Thread 1 - returns from exec to find message on the queue #Thread 1 - returns the result to the prompt() call. I'm not really sure how to easily add a flag to avoid this optimization given the current structure of the code. Maybe have pluginManager.exec return a boolean indicating async vs sync. Or just don't worry about it
          Hide
          Andrew Grieve added a comment -

          That turned out to be it. I added a flag to disable the optimization and HANGING_GET got a lot slower.

          I tried to get your benchmark to be more accurate by disabling setTimeout and adding in delays, but it's still not quite giving the same results as the manual page I created.

          I also played with using benchmark.js to measure the times, but it gives ops/second that are far below what the manual test page shows. I suspect it's from it's use of setTimeout when using deferred tests, but I found the source code of benchmark.js to be quite confusing, so gave up on it.

          In case you're interested, I pushed it to my github as a separate entry in the auto-tests page. I'm not planning on committing it though, as I think the manual test page does a better job at measuring.

          https://github.com/agrieve/incubator-cordova-mobile-spec/tree/bench

          Show
          Andrew Grieve added a comment - That turned out to be it. I added a flag to disable the optimization and HANGING_GET got a lot slower. I tried to get your benchmark to be more accurate by disabling setTimeout and adding in delays, but it's still not quite giving the same results as the manual page I created. I also played with using benchmark.js to measure the times, but it gives ops/second that are far below what the manual test page shows. I suspect it's from it's use of setTimeout when using deferred tests, but I found the source code of benchmark.js to be quite confusing, so gave up on it. In case you're interested, I pushed it to my github as a separate entry in the auto-tests page. I'm not planning on committing it though, as I think the manual test page does a better job at measuring. https://github.com/agrieve/incubator-cordova-mobile-spec/tree/bench
          Hide
          Andrew Grieve added a comment -

          New bridge options are as much as 25X faster. There's a new issue for changing the default to ONLINE_EVENTS:
          https://issues.apache.org/jira/browse/CB-1498

          Show
          Andrew Grieve added a comment - New bridge options are as much as 25X faster. There's a new issue for changing the default to ONLINE_EVENTS: https://issues.apache.org/jira/browse/CB-1498

            People

            • Assignee:
              Andrew Grieve
              Reporter:
              Lee Crossley
            • Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development