Show rect/enc counts, add vnc_perf.html test.
- include/rfb.js: Keep track of the number of rects of each encoding type and print them out when we close a connection (if 'info' logging level). - tests/vnc_perf.html: first pass at a noVNC based performance benchmark. - utils/wsproxy.py: Fix the output of the record filename.
This commit is contained in:
parent
3b20e7a90f
commit
a679a97d1b
|
@ -18,7 +18,7 @@ var that = {}, // Public API interface
|
|||
|
||||
// Pre-declare private functions used before definitions (jslint)
|
||||
init_vars, updateState, init_msg, normal_msg, recv_message,
|
||||
framebufferUpdate,
|
||||
framebufferUpdate, print_stats,
|
||||
|
||||
pixelFormat, clientEncodings, fbUpdateRequest,
|
||||
keyEvent, pointerEvent, clientCutText,
|
||||
|
@ -61,6 +61,7 @@ var that = {}, // Public API interface
|
|||
|
||||
encHandlers = {},
|
||||
encNames = {},
|
||||
encStats = {}, // [rectCnt, rectCntTot]
|
||||
|
||||
ws = null, // Web Socket object
|
||||
canvas = null, // Canvas object
|
||||
|
@ -216,6 +217,7 @@ function constructor() {
|
|||
for (i=0; i < encodings.length; i+=1) {
|
||||
encHandlers[encodings[i][1]] = encHandlers[encodings[i][0]];
|
||||
encNames[encodings[i][1]] = encodings[i][0];
|
||||
encStats[encodings[i][1]] = [0, 0];
|
||||
}
|
||||
// Initialize canvas
|
||||
try {
|
||||
|
@ -309,6 +311,32 @@ init_vars = function() {
|
|||
FBU.imgQ = []; // TIGHT_PNG image queue
|
||||
mouse_buttonMask = 0;
|
||||
mouse_arr = [];
|
||||
|
||||
// Clear the per connection encoding stats
|
||||
for (i=0; i < encodings.length; i+=1) {
|
||||
encStats[encodings[i][1]][0] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Print statistics
|
||||
print_stats = function() {
|
||||
var i, encName, s;
|
||||
Util.Info("Encoding stats for this connection:");
|
||||
for (i=0; i < encodings.length; i+=1) {
|
||||
s = encStats[encodings[i][1]];
|
||||
if ((s[0] + s[1]) > 0) {
|
||||
Util.Info(" " + encodings[i][0] + ": " +
|
||||
s[0] + " rects");
|
||||
}
|
||||
}
|
||||
Util.Info("Encoding stats since page load:");
|
||||
for (i=0; i < encodings.length; i+=1) {
|
||||
s = encStats[encodings[i][1]];
|
||||
if ((s[0] + s[1]) > 0) {
|
||||
Util.Info(" " + encodings[i][0] + ": "
|
||||
+ s[1] + " rects");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -440,6 +468,8 @@ updateState = function(state, statusMsg) {
|
|||
}, conf.disconnectTimeout * 1000);
|
||||
}
|
||||
|
||||
print_stats();
|
||||
|
||||
// WebSocket.onclose transitions to 'disconnected'
|
||||
break;
|
||||
|
||||
|
@ -944,7 +974,7 @@ normal_msg = function() {
|
|||
};
|
||||
|
||||
framebufferUpdate = function() {
|
||||
var now, hdr, fbu_rt_diff, last_bytes, last_rects, ret = true;
|
||||
var now, hdr, fbu_rt_diff, ret = true, ctx;
|
||||
|
||||
if (FBU.rects === 0) {
|
||||
//Util.Debug("New FBU: rQ.slice(0,20): " + rQ.slice(0,20));
|
||||
|
@ -1011,15 +1041,17 @@ framebufferUpdate = function() {
|
|||
}
|
||||
|
||||
timing.last_fbu = (new Date()).getTime();
|
||||
last_bytes = rQlen();
|
||||
last_rects = FBU.rects;
|
||||
|
||||
// false ret means need more data
|
||||
ret = encHandlers[FBU.encoding]();
|
||||
|
||||
now = (new Date()).getTime();
|
||||
timing.cur_fbu += (now - timing.last_fbu);
|
||||
|
||||
if (ret) {
|
||||
encStats[FBU.encoding][0] += 1;
|
||||
encStats[FBU.encoding][1] += 1;
|
||||
}
|
||||
|
||||
if (FBU.rects === 0) {
|
||||
if (((FBU.width === fb_width) &&
|
||||
(FBU.height === fb_height)) ||
|
||||
|
@ -1058,7 +1090,7 @@ framebufferUpdate = function() {
|
|||
//
|
||||
|
||||
encHandlers.RAW = function display_raw() {
|
||||
//Util.Debug(">> display_raw");
|
||||
//Util.Debug(">> display_raw (" + rQlen() + " bytes)");
|
||||
|
||||
var cur_y, cur_height;
|
||||
|
||||
|
@ -1084,6 +1116,7 @@ encHandlers.RAW = function display_raw() {
|
|||
FBU.rects -= 1;
|
||||
FBU.bytes = 0;
|
||||
}
|
||||
//Util.Debug("<< display_raw (" + rQlen() + " bytes)");
|
||||
return true;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,197 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>VNC Performance Benchmark</title>
|
||||
<link rel="stylesheet" href="include/plain.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
Passes: <input id='passes' style='width:50' value=3>
|
||||
|
||||
<input id='startButton' type='button' value='Start' style='width:100px'
|
||||
onclick="start();" disabled>
|
||||
|
||||
<br><br>
|
||||
|
||||
Results:<br>
|
||||
<textarea id="messages" style="font-size: 9;" cols=80 rows=15></textarea>
|
||||
|
||||
<br><br>
|
||||
|
||||
<div id="VNC_screen">
|
||||
<div id="VNC_status_bar" class="VNC_status_bar" style="margin-top: 0px;">
|
||||
<table border=0 width=100%><tr>
|
||||
<td><div id="VNC_status">Loading</div></td>
|
||||
</tr></table>
|
||||
</div>
|
||||
<canvas id="VNC_canvas" width="640px" height="20px">
|
||||
Canvas not supported.
|
||||
</canvas>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
<!--
|
||||
<script type='text/javascript'
|
||||
src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>
|
||||
-->
|
||||
|
||||
<script src="include/vnc.js"></script>
|
||||
<script src="include/playback.js"></script>
|
||||
<script src="data_multi.js"></script>
|
||||
|
||||
<script>
|
||||
var start_time, VNC_frame_data, pass, passes, encIdx,
|
||||
encOrder = ['raw', 'rre', 'hextile', 'tightpng', 'copyrect'],
|
||||
encTot = {}, encMin = {}, encMax = {},
|
||||
passCur, passTot, passMin, passMax;
|
||||
|
||||
function msg(str) {
|
||||
console.log(str);
|
||||
var cell = $('messages');
|
||||
cell.innerHTML += str + "\n";
|
||||
cell.scrollTop = cell.scrollHeight;
|
||||
}
|
||||
function dbgmsg(str) {
|
||||
if (Util.get_logging() === 'debug') {
|
||||
msg(str);
|
||||
}
|
||||
}
|
||||
|
||||
updateState = function (rfb, state, oldstate, mesg) {
|
||||
switch (state) {
|
||||
case 'failed':
|
||||
case 'fatal':
|
||||
msg("noVNC sent '" + state +
|
||||
"' state during pass " + pass +
|
||||
", iteration " + iteration +
|
||||
" frame " + frame_idx);
|
||||
test_state = 'failed';
|
||||
break;
|
||||
case 'loaded':
|
||||
$('startButton').disabled = false;
|
||||
break;
|
||||
}
|
||||
if (typeof mesg !== 'undefined') {
|
||||
$('VNC_status').innerHTML = mesg;
|
||||
}
|
||||
}
|
||||
|
||||
function start() {
|
||||
$('startButton').value = "Running";
|
||||
$('startButton').disabled = true;
|
||||
|
||||
mode = 'perftest'; // full-speed
|
||||
passes = $('passes').value;
|
||||
pass = 1;
|
||||
encIdx = 0;
|
||||
|
||||
// Render each encoding once for each pass
|
||||
iterations = 1;
|
||||
|
||||
// Initialize stats counters
|
||||
for (i = 0; i < encOrder.length; i++) {
|
||||
enc = encOrder[i];
|
||||
encTot[i] = 0;
|
||||
encMin[i] = 2<<23; // Something sufficiently large
|
||||
encMax[i] = 0;
|
||||
}
|
||||
passCur = 0;
|
||||
passTot = 0;
|
||||
passMin = 2<<23;
|
||||
passMax = 0;
|
||||
|
||||
// Fire away
|
||||
next_encoding();
|
||||
}
|
||||
|
||||
function next_encoding() {
|
||||
var encName;
|
||||
|
||||
if (encIdx >= encOrder.length) {
|
||||
// Accumulate pass stats
|
||||
if (passCur < passMin) {
|
||||
passMin = passCur;
|
||||
}
|
||||
if (passCur > passMax) {
|
||||
passMax = passCur;
|
||||
}
|
||||
msg("Pass " + pass + " took " + passCur + " ms");
|
||||
|
||||
passCur = 0;
|
||||
encIdx = 0;
|
||||
pass += 1;
|
||||
if (pass > passes) {
|
||||
// We are finished
|
||||
rfb.get_canvas().stop(); // Shut-off event interception
|
||||
$('startButton').disabled = false;
|
||||
$('startButton').value = "Start";
|
||||
finish_passes();
|
||||
return; // We are finished, terminate
|
||||
}
|
||||
}
|
||||
|
||||
encName = encOrder[encIdx];
|
||||
dbgmsg("Rendering pass " + pass + " encoding '" + encName + "'");
|
||||
|
||||
VNC_frame_data = VNC_frame_data_multi[encName];
|
||||
iteration = 0;
|
||||
start_time = (new Date()).getTime();
|
||||
|
||||
next_iteration();
|
||||
}
|
||||
|
||||
// Finished rendering current encoding
|
||||
function finish() {
|
||||
var total_time, end_time = (new Date()).getTime();
|
||||
total_time = end_time - start_time;
|
||||
|
||||
dbgmsg("Encoding " + encOrder[encIdx] + " took " + total_time + "ms");
|
||||
|
||||
passCur += total_time;
|
||||
passTot += total_time;
|
||||
|
||||
// Accumulate stats
|
||||
encTot[encIdx] += total_time;
|
||||
if (total_time < encMin[encIdx]) {
|
||||
encMin[encIdx] = total_time;
|
||||
}
|
||||
if (total_time > encMax[encIdx]) {
|
||||
encMax[encIdx] = total_time;
|
||||
}
|
||||
|
||||
encIdx += 1;
|
||||
next_encoding();
|
||||
}
|
||||
|
||||
function finish_passes() {
|
||||
var i, enc, avg, passAvg;
|
||||
msg("STATS (for " + passes + " passes)");
|
||||
// Encoding stats
|
||||
for (i = 0; i < encOrder.length; i++) {
|
||||
enc = encOrder[i];
|
||||
avg = (encTot[i] / passes).toFixed(1);
|
||||
msg(" " + enc + ": " + encTot[i] + " ms, " +
|
||||
encMin[i] + "/" + avg + "/" + encMax[i] +
|
||||
" (min/avg/max)");
|
||||
|
||||
}
|
||||
// Print pass stats
|
||||
passAvg = (passTot / passes).toFixed(1);
|
||||
msg("\n All passes: " + passTot + " ms, " +
|
||||
passMin + "/" + passAvg + "/" + passMax +
|
||||
" (min/avg/max)");
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
var i, enc;
|
||||
dbgmsg("Frame lengths:");
|
||||
for (i = 0; i < encOrder.length; i++) {
|
||||
enc = encOrder[i];
|
||||
dbgmsg(" " + enc + ": " + VNC_frame_data_multi[enc].length);
|
||||
}
|
||||
rfb = RFB({'target': 'VNC_canvas',
|
||||
'updateState': updateState});
|
||||
rfb.testMode(send_array);
|
||||
}
|
||||
</script>
|
||||
</html>
|
|
@ -101,12 +101,13 @@ def do_proxy(client, target):
|
|||
cpartial = cpartial + buf
|
||||
|
||||
def proxy_handler(client):
|
||||
global target_host, target_port, options, rec
|
||||
global target_host, target_port, options, rec, fname
|
||||
|
||||
if settings['record']:
|
||||
handler_msg("opening record file: %s" % settings['record'])
|
||||
rec = open("%s.%s" % (settings['record'],
|
||||
settings['handler_id']), 'w+')
|
||||
fname = "%s.%s" % (settings['record'],
|
||||
settings['handler_id'])
|
||||
handler_msg("opening record file: %s" % fname)
|
||||
rec = open(fname, 'w+')
|
||||
rec.write("var VNC_frame_data = [\n")
|
||||
|
||||
handler_msg("connecting to: %s:%s" % (target_host, target_port))
|
||||
|
|
Loading…
Reference in New Issue