| <!DOCTYPE html> |
| <!-- |
| |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| |
| --> |
| |
| |
| <html> |
| <head> |
| <meta name="viewport" content="width=device-width,height=device-height,user-scalable=no,maximum-scale=1.0,initial-scale=1.0" /> |
| <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <!-- ISO-8859-1 --> |
| <title>Cordova Mobile Spec</title> |
| <link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title" charset="utf-8"> |
| <script src="../cordova-incl.js"></script> |
| <script src="setImmediate.js"></script> |
| <script> |
| var exec = cordova.require('cordova/exec'), |
| appLogElem = null, |
| deviceReady = false, |
| inProgress = false; |
| |
| function appLog(message) { |
| if (!appLogElem) { |
| appLogElem = document.getElementById('app-logs'); |
| } |
| appLogElem.innerText += message + '\n'; |
| if (window.console) { |
| console.log(message); |
| } |
| } |
| |
| function clearLogs() { |
| appLogElem.innerHTML = ''; |
| } |
| |
| function updateUi(val) { |
| inProgress = val; |
| var goBtn = document.getElementById('go-btn'); |
| goBtn.textContent = inProgress ? 'Stop' : 'Start'; |
| cordova.echo.stopBulkEcho(); |
| } |
| |
| function createPayload(size, binary) { |
| if (!binary) { |
| return new Array(size * 10 + 1).join('012\n\n 6789'); |
| } |
| size = size * 100; |
| var bufView = new Uint8Array(size); |
| for (var i = 0; i < size; ++i) { |
| bufView[i] = i % 20; |
| } |
| return bufView.buffer; |
| } |
| |
| function benchExec() { |
| updateUi(!inProgress); |
| if (!inProgress) { |
| return; |
| } |
| |
| var echo = cordova.echo, |
| startTime = +new Date, |
| callCount = 0, |
| elapsedMs, |
| lastReportMs = 0, |
| durationMs = parseInt(document.getElementById('test-duration').value, 10) * 1000, |
| asyncEcho = document.getElementById('async-echo').checked, |
| useSetTimeout = document.getElementById('use-setTimeout').checked, |
| bulkEcho = document.getElementById('bulk-echo').checked, |
| jsToNativeMode = document.getElementById('js-native-modes').value, |
| nativeToJsMode = document.getElementById('native-js-modes').value, |
| payloadSize = +document.getElementById('payload-size').value, |
| binaryPayload = document.getElementById('binary-payload').checked, |
| binaryAsyncEncode = document.getElementById('binary-async-encode').checked, |
| binaryAsyncDecode = document.getElementById('binary-async-decode').checked, |
| soFarEl = document.getElementById('so-far'), |
| payload = createPayload(payloadSize, binaryPayload); |
| |
| cordova.ASYNC_AB_ENCODE = binaryAsyncEncode; |
| cordova.ASYNC_AB_DECODE = binaryAsyncDecode; |
| |
| function reportProgress() { |
| var callsPerSecond = String(callCount * 1000 / elapsedMs).slice(0, 6); |
| soFarEl.textContent = callsPerSecond + ' ops'; |
| appLog('Calls per second: ' + callsPerSecond); |
| } |
| function win(result) { |
| if (!inProgress) { |
| console.log('got an excess echo'); |
| return; |
| } |
| callCount++; |
| if (result.length !== payload.length || result.byteLength !== payload.byteLength) { |
| appLog('Wrong echo data!'); |
| updateUi(false); |
| } |
| elapsedMs = new Date - startTime; |
| if (inProgress && elapsedMs < durationMs) { |
| if (elapsedMs - lastReportMs > 1000) { |
| reportProgress(); |
| lastReportMs = elapsedMs; |
| } |
| if (bulkEcho) { |
| // automatically keeps coming. |
| } else if (useSetTimeout) { |
| setImmediate(echoMessage); |
| } else { |
| echoMessage(); |
| } |
| } else { |
| reportProgress(); |
| updateUi(false); |
| } |
| } |
| function fail() { |
| appLog('Call failed!'); |
| } |
| function echoMessage() { |
| echo(win, fail, payload, asyncEcho); |
| } |
| |
| var logMsg = 'Started exec benchmark with setImmediate: ' + useSetTimeout + ' asyncEcho: ' + asyncEcho + ' payload length: ' + payloadSize; |
| if (jsToNativeMode) { |
| exec.setJsToNativeBridgeMode(+jsToNativeMode); |
| logMsg += ' jsToNativeMode: ' + jsToNativeMode; |
| } |
| if (nativeToJsMode) { |
| exec.setNativeToJsBridgeMode(+nativeToJsMode); |
| logMsg += ' nativeToJsMode: ' + nativeToJsMode; |
| } |
| appLog(logMsg); |
| if (bulkEcho) { |
| echo.bulkEcho(payload, 50, win); |
| } else { |
| echoMessage(); |
| } |
| setTimeout(function() { |
| if (!callCount) { |
| alert('Echo plugin did not respond'); |
| } |
| }, 500); |
| } |
| |
| function configureDragMe() { |
| var dragMeEl = document.getElementById('drag-me'); |
| dragMeEl.ontouchmove = function(e) { |
| e.preventDefault(); |
| var touch = e.touches[0]; |
| dragMeEl.style.left = touch.pageX - 50 + 'px'; |
| dragMeEl.style.top = touch.pageY - 50 + 'px'; |
| } |
| } |
| function configure() { |
| function configureModes(elemId, modes) { |
| var selectElem = document.getElementById(elemId); |
| for (var modeName in modes) { |
| var optionElem = document.createElement('option'); |
| optionElem.value = modes[modeName]; |
| optionElem.innerText = modeName; |
| selectElem.appendChild(optionElem); |
| } |
| selectElem.parentNode.style.display = 'block'; |
| } |
| if (exec.jsToNativeModes) { |
| configureModes('js-native-modes', exec.jsToNativeModes); |
| } |
| if (exec.nativeToJsModes) { |
| configureModes('native-js-modes', exec.nativeToJsModes); |
| } |
| configureDragMe(); |
| } |
| |
| |
| document.addEventListener("deviceready", function() { |
| deviceReady = true; |
| appLog("Device="+device.platform+" "+device.version); |
| configure(); |
| }, false); |
| |
| window.onload = function() { |
| window.setTimeout(function() { |
| if (!deviceReady) { |
| alert("Error: Cordova did not initialize. Demo will not run correctly."); |
| } |
| }, 1000); |
| }; |
| |
| </script> |
| |
| </head> |
| <body id="stage" class="theme"> |
| <h1>exec() Benchmark</h1> |
| Before running on Android, set the following constants in NativeToJsMessagingBridge: |
| <ul> |
| <li>ENABLE_LOCATION_CHANGE_EXEC_MODE = true |
| <li>DISABLE_EXEC_CHAINING = true |
| </ul> |
| As of iOS 7.0.2, Andrew found that the iframe bridge is still the fastest on iOS. |
| <fieldset> |
| <legend>Settings</legend> |
| <label>Test Duration: <select id="test-duration"><option>1 Second</option><option>3 Seconds</option><option>10 seconds</option></select><br></label> |
| <label style="display:none">JS->Native Bridge Mode: <select id="js-native-modes"></select><br></label> |
| <label style="display:none">Native->JS Bridge Mode: <select id="native-js-modes"></select><br></label> |
| <label><input type="checkbox" id="use-setTimeout"> Force async JS->Native (avoids evalAndFetch optimization on iOS)</label><br> |
| <label><input type="checkbox" id="async-echo"> Force async Native->JS</label><br> |
| <label><input type="checkbox" id="bulk-echo"> Bulk Echo Mode (test only native->JS)</label><br> |
| <label><input type="checkbox" id="binary-payload"> Binary Payload</label><br> |
| These two require async_base64_android branch of cordova-js<br> |
| <label><input type="checkbox" id="binary-async-encode"> Use FileReader to encode binary</label><br> |
| <label><input type="checkbox" id="binary-async-decode"> Use XHR to decode binary</label><br> |
| <label>Payload size (in 100s of bytes) <input id="payload-size" value="5" style="width:100px"></label><br> |
| <button id="go-btn" onclick="benchExec()">Start</button><br> |
| </fieldset> |
| <div>some text.<br> |
| <div style="position:absolute;height:100px;background:red;width:100px;left:250px;top:50px;z-index:5" id="drag-me">Drag Me<div id="so-far"></div></div> |
| <input value="dummy input"> text box to see if focus is lost by bridge or if there is typing lag. |
| </div> |
| <h2> </h2><a href="javascript:" class="backBtn" onclick="backHome();">Back</a><br> |
| <div>Results: <a href="javascript:clearLogs();">Clear</a></div> |
| <pre id="app-logs" style="white-space:pre-wrap;line-height:initial; margin-bottom:500px"></pre> |
| You've reached the bottom. |
| </body> |
| </html> |