10b9e1f47d
The MPL 2.0 license is a "file-level" copyleft license vs the "project-level" nature of the L/GPL. The intention of noVNC has always been that it should be easy to incorporate into existing projects and sites whether free/open or proprietary/commercial. The MPL 2.0 is designed for this sort of combination project but still requires that any distributed modifications to noVNC source files must also be published under the same license. In addition, the MPL 2.0 allows the code to be used in L/GPL projects (the secondary license clause). This means that any projects that are already incorporating noVNC should not be impacted by this change and in fact it should clarify the licensing situation (the exact application of the L/GPL to web applications and interpreted code is somewhat ambiguous). The HTML, CSS, image and font files continue to be under more permissive licenses (see LICENSE.txt). The included websockify python code remains under a LGPLv3 license although the include/websock.js file from the websockify component is now under MPL 2.0 as well. Permission was received from other noVNC authors to make this change to their code license on the following dates: - Chris Gordon (UI): Jun 24, 2012 - Antoine Mercadal (DOM,*util.js): Oct 10, 2012 - William Lightning (UltraVNC repeater): Oct 10, 2012 - Mike Tinglof (tight encoding): Oct 15, 2012
376 lines
10 KiB
JavaScript
376 lines
10 KiB
JavaScript
/*
|
|
* Javascript binary array performance tests
|
|
* Copyright (C) 2012 Joel Martin
|
|
* Licensed under MPL 2.0 (see LICENSE.txt)
|
|
*/
|
|
|
|
var ctx, i, j, randlist,
|
|
new_normal, new_imageData, new_arrayBuffer,
|
|
browser = Browser.browser + " " +
|
|
Browser.version + " on " +
|
|
Browser.OS,
|
|
do_imageData = false,
|
|
do_arrayBuffer = false,
|
|
conf = {
|
|
'create_cnt' : 2000,
|
|
'read_cnt' : 5000000,
|
|
'write_cnt' : 5000000,
|
|
'iterations' : 0,
|
|
'order_l1' : [browser],
|
|
'order_l2' : ['normal',
|
|
'imageData',
|
|
'arrayBuffer'],
|
|
'order_l3' : ['create',
|
|
'sequentialRead',
|
|
'randomRead',
|
|
'sequentialWrite']
|
|
},
|
|
stats = {},
|
|
testFunc = {},
|
|
iteration, arraySize;
|
|
|
|
var newline = "\n";
|
|
if (Util.Engine.trident) {
|
|
var newline = "<br>\n";
|
|
}
|
|
function message(str) {
|
|
//console.log(str);
|
|
cell = $D('messages');
|
|
cell.innerHTML += str + newline;
|
|
cell.scrollTop = cell.scrollHeight;
|
|
}
|
|
|
|
function vmessage(str) {
|
|
if (verbose) {
|
|
message(str);
|
|
} else {
|
|
console.log(str);
|
|
}
|
|
}
|
|
|
|
new_normal = function() {
|
|
var arr = [], i;
|
|
for (i = 0; i < arraySize; i++) {
|
|
arr[i] = 0;
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
/* Will be overridden with real function */
|
|
new_imageData = function() {
|
|
throw("imageData not supported");
|
|
};
|
|
|
|
new_imageData_createImageData = function() {
|
|
var imageData = ctx.createImageData(1024/4, arraySize / 1024);
|
|
return imageData.data;
|
|
};
|
|
|
|
new_imageData_getImageData = function() {
|
|
var imageData = ctx.getImageData(0, 0, 1024/4, arraySize / 1024),
|
|
arr = imageData.data;
|
|
for (i = 0; i < arraySize; i++) {
|
|
arr[i] = 0;
|
|
}
|
|
return arr;
|
|
};
|
|
|
|
new_arrayBuffer = function() {
|
|
var arr = new ArrayBuffer(arraySize);
|
|
return new Uint8Array(arr);
|
|
}
|
|
|
|
function init_randlist() {
|
|
randlist = [];
|
|
for (var i=0; i < arraySize; i++) {
|
|
randlist[i] = parseInt(Math.random() * 256, 10);
|
|
}
|
|
}
|
|
function copy_randlist(arr) {
|
|
for (var i=0; i < arraySize; i++) {
|
|
arr[i] = randlist[i];
|
|
}
|
|
}
|
|
|
|
function begin() {
|
|
var i, j;
|
|
conf.iterations = parseInt($D('iterations').value, 10);
|
|
arraySize = parseInt($D('arraySize').value, 10) * 1024;
|
|
|
|
init_randlist();
|
|
|
|
// TODO: randomize test_list
|
|
|
|
stats = {};
|
|
for (i = 0; i < conf.order_l2.length; i++) {
|
|
stats[conf.order_l2[i]] = {};
|
|
for (j = 0; j < conf.order_l3.length; j++) {
|
|
stats[conf.order_l2[i]][conf.order_l3[j]] = [];
|
|
}
|
|
}
|
|
|
|
$D('startButton').value = "Running";
|
|
$D('startButton').disabled = true;
|
|
|
|
message("running " + conf.iterations + " test iterations");
|
|
iteration = 1;
|
|
setTimeout(run_next_iteration, 250);
|
|
}
|
|
|
|
function finish() {
|
|
var totalTime, arrayType, testType, times;
|
|
message("tests finished");
|
|
|
|
for (j = 0; j < conf.order_l3.length; j++) {
|
|
testType = conf.order_l3[j];
|
|
message("Test '" + testType + "'");
|
|
for (i = 0; i < conf.order_l2.length; i++) {
|
|
arrayType = conf.order_l2[i];
|
|
message(" Array Type '" + arrayType);
|
|
times = stats[arrayType][testType];
|
|
message(" Average : " + times.mean() + "ms" +
|
|
" (Total: " + times.sum() + "ms)");
|
|
message(" Min/Max : " + times.min() + "ms/" +
|
|
times.max() + "ms");
|
|
message(" StdDev : " + times.stdDev() + "ms");
|
|
}
|
|
}
|
|
|
|
vmessage("array_chart.py JSON data:");
|
|
chart_data = {'conf' : conf, 'stats' : { } };
|
|
chart_data.stats[browser] = stats;
|
|
chart_data.stats['next_browser'] = {};
|
|
vmessage(JSON.stringify(chart_data, null, 2));
|
|
|
|
$D('startButton').disabled = false;
|
|
$D('startButton').value = "Run Tests";
|
|
}
|
|
|
|
function run_next_iteration() {
|
|
var arrayType, testType, deltaTime;
|
|
|
|
for (i = 0; i < conf.order_l2.length; i++) {
|
|
arrayType = conf.order_l2[i];
|
|
if (arrayType === 'imageData' && (!do_imageData)) {
|
|
continue;
|
|
}
|
|
if (arrayType === 'arrayBuffer' && (!do_arrayBuffer)) {
|
|
continue;
|
|
}
|
|
for (j = 0; j < conf.order_l3.length; j++) {
|
|
testType = conf.order_l3[j];
|
|
|
|
deltaTime = testFunc[arrayType + "_" + testType]();
|
|
|
|
stats[arrayType][testType].push(deltaTime);
|
|
vmessage("test " + (arrayType + "_" + testType) +
|
|
" time: " + (deltaTime) + "ms");
|
|
}
|
|
}
|
|
|
|
message("finished test iteration " + iteration);
|
|
if (iteration >= conf.iterations) {
|
|
setTimeout(finish, 1);
|
|
return;
|
|
}
|
|
iteration++;
|
|
setTimeout(run_next_iteration, 1);
|
|
}
|
|
|
|
/*
|
|
* Test functions
|
|
*/
|
|
|
|
testFunc["normal_create"] = function() {
|
|
var cnt, arrNormal, startTime, endTime;
|
|
vmessage("create normal array " + conf.create_cnt + "x, initialized to 0");
|
|
|
|
startTime = (new Date()).getTime();
|
|
for (cnt = 0; cnt < conf.create_cnt; cnt++) {
|
|
arrNormal = new_normal();
|
|
}
|
|
endTime = (new Date()).getTime();
|
|
|
|
return endTime - startTime;
|
|
};
|
|
|
|
testFunc["imageData_create"] = function() {
|
|
var cnt, arrImage, startTime, endTime;
|
|
vmessage("create imageData array " + conf.create_cnt + "x, initialized to 0");
|
|
|
|
startTime = (new Date()).getTime();
|
|
for (cnt = 0; cnt < conf.create_cnt; cnt++) {
|
|
arrImage = new_imageData();
|
|
}
|
|
endTime = (new Date()).getTime();
|
|
|
|
if (arrImage[103] !== 0) {
|
|
message("Initialization failed, arrImage[103] is: " + arrImage[103]);
|
|
throw("Initialization failed, arrImage[103] is: " + arrImage[103]);
|
|
}
|
|
return endTime - startTime;
|
|
};
|
|
|
|
testFunc["arrayBuffer_create"] = function() {
|
|
var cnt, arrBuffer, startTime, endTime;
|
|
vmessage("create arrayBuffer array " + conf.create_cnt + "x, initialized to 0");
|
|
|
|
startTime = (new Date()).getTime();
|
|
for (cnt = 0; cnt < conf.create_cnt; cnt++) {
|
|
arrBuffer = new_arrayBuffer();
|
|
}
|
|
endTime = (new Date()).getTime();
|
|
|
|
if (arrBuffer[103] !== 0) {
|
|
message("Initialization failed, arrBuffer[103] is: " + arrBuffer[103]);
|
|
throw("Initialization failed, arrBuffer[103] is: " + arrBuffer[103]);
|
|
}
|
|
return endTime - startTime;
|
|
};
|
|
|
|
function test_sequentialRead(arr) {
|
|
var i, j, cnt, startTime, endTime;
|
|
/* Initialize the array */
|
|
copy_randlist(arr);
|
|
|
|
startTime = (new Date()).getTime();
|
|
i = 0;
|
|
j = 0;
|
|
for (cnt = 0; cnt < conf.read_cnt; cnt++) {
|
|
j = arr[i];
|
|
i++;
|
|
if (i >= arraySize) {
|
|
i = 0;
|
|
}
|
|
}
|
|
endTime = (new Date()).getTime();
|
|
|
|
return endTime - startTime;
|
|
}
|
|
|
|
function test_randomRead(arr) {
|
|
var i, cnt, startTime, endTime;
|
|
/* Initialize the array */
|
|
copy_randlist(arr); // used as jumplist
|
|
|
|
startTime = (new Date()).getTime();
|
|
i = 0;
|
|
for (cnt = 0; cnt < conf.read_cnt; cnt++) {
|
|
i = (arr[i] + cnt) % arraySize;
|
|
}
|
|
endTime = (new Date()).getTime();
|
|
|
|
return endTime - startTime;
|
|
}
|
|
|
|
function test_sequentialWrite(arr) {
|
|
var i, cnt, startTime, endTime;
|
|
/* Initialize the array */
|
|
copy_randlist(arr);
|
|
|
|
startTime = (new Date()).getTime();
|
|
i = 0;
|
|
for (cnt = 0; cnt < conf.write_cnt; cnt++) {
|
|
arr[i] = (cnt % 256);
|
|
i++;
|
|
if (i >= arraySize) {
|
|
i = 0;
|
|
}
|
|
}
|
|
endTime = (new Date()).getTime();
|
|
|
|
return endTime - startTime;
|
|
}
|
|
|
|
/* Sequential Read Tests */
|
|
testFunc["normal_sequentialRead"] = function() {
|
|
vmessage("read normal array " + conf.read_cnt + "x");
|
|
return test_sequentialRead(new_normal());
|
|
};
|
|
|
|
testFunc["imageData_sequentialRead"] = function() {
|
|
vmessage("read imageData array " + conf.read_cnt + "x");
|
|
return test_sequentialRead(new_imageData());
|
|
};
|
|
|
|
testFunc["arrayBuffer_sequentialRead"] = function() {
|
|
vmessage("read arrayBuffer array " + conf.read_cnt + "x");
|
|
return test_sequentialRead(new_arrayBuffer());
|
|
};
|
|
|
|
|
|
/* Random Read Tests */
|
|
testFunc["normal_randomRead"] = function() {
|
|
vmessage("read normal array " + conf.read_cnt + "x");
|
|
return test_randomRead(new_normal());
|
|
};
|
|
|
|
testFunc["imageData_randomRead"] = function() {
|
|
vmessage("read imageData array " + conf.read_cnt + "x");
|
|
return test_randomRead(new_imageData());
|
|
};
|
|
|
|
testFunc["arrayBuffer_randomRead"] = function() {
|
|
vmessage("read arrayBuffer array " + conf.read_cnt + "x");
|
|
return test_randomRead(new_arrayBuffer());
|
|
};
|
|
|
|
|
|
/* Sequential Write Tests */
|
|
testFunc["normal_sequentialWrite"] = function() {
|
|
vmessage("write normal array " + conf.write_cnt + "x");
|
|
return test_sequentialWrite(new_normal());
|
|
};
|
|
|
|
testFunc["imageData_sequentialWrite"] = function() {
|
|
vmessage("write imageData array " + conf.write_cnt + "x");
|
|
return test_sequentialWrite(new_imageData());
|
|
};
|
|
|
|
testFunc["arrayBuffer_sequentialWrite"] = function() {
|
|
vmessage("write arrayBuffer array " + conf.write_cnt + "x");
|
|
return test_sequentialWrite(new_arrayBuffer());
|
|
};
|
|
|
|
init = function() {
|
|
vmessage(">> init");
|
|
|
|
$D('iterations').value = 10;
|
|
$D('arraySize').value = 10;
|
|
arraySize = parseInt($D('arraySize').value, 10) * 1024;
|
|
|
|
message("Browser: " + browser);
|
|
|
|
/* Determine browser binary array support */
|
|
try {
|
|
ctx = $D('canvas').getContext('2d');
|
|
new_imageData = new_imageData_createImageData;
|
|
new_imageData();
|
|
do_imageData = true;
|
|
} catch (exc) {
|
|
vmessage("createImageData not supported: " + exc);
|
|
try {
|
|
ctx = $D('canvas').getContext('2d');
|
|
new_imageData = new_imageData_getImageData;
|
|
blah = new_imageData();
|
|
do_imageData = true;
|
|
} catch (exc) {
|
|
vmessage("getImageData not supported: " + exc);
|
|
}
|
|
}
|
|
if (! do_imageData) {
|
|
message("imageData arrays not supported");
|
|
}
|
|
|
|
try {
|
|
new_arrayBuffer();
|
|
do_arrayBuffer = true;
|
|
} catch (exc) {
|
|
vmessage("Typed Arrays not supported: " + exc);
|
|
}
|
|
if (! do_arrayBuffer) {
|
|
message("Typed Arrays (ArrayBuffers) not suppoted");
|
|
}
|
|
vmessage("<< init");
|
|
}
|