<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Chapter 6 : Networking Considerations - Payload Partitioning Explorer</title>
<link rel="stylesheet" href="https://ajaxref.com/ch6/global.css" type="text/css" media="screen" />
#responseOutput {
height:200px;
overflow:auto;
}
#lines_legend{
margin-left:50px;
width:930px;
}
<script type="text/javascript" src="https://ajaxref.com/ch6/ajaxtcr.js" >
<script type="text/javascript" src="https://ajaxref.com/lib/prototype1.5.1/prototype.js" >
<script type="text/javascript" src="https://ajaxref.com/lib/excanvas/excanvas.js" >
<script type="text/javascript" src="https://ajaxref.com/lib/plotr/plotr.js" >
<script type="text/javascript">
var gSend = 1;
var gLine = null;
var gLatency = 0;
function handleResults(response)
{
var allRequests = response.allRequests;
var payload = AjaxTCR.data.decodeJSON(response.xhr.responseText);
calculateGraph(allRequests, payload);
}
function handleResponse(response)
{
var requestObject = response.requestObject;
var allRequests = response.allRequests;
requestObject.returned++;
if (requestObject.runs == requestObject.returned)
{
var endTime = (new Date()).getTime();
requestObject.requestTime = (endTime - requestObject.startTime)/1000;
var responseOutput = document.getElementById("responseOutput");
if (gSend == 0)
responseOutput.innerHTML += "<h2>TEST STOPPED IN PROGRESS</h2>";
else
{
if (requestObject.runs == 1)
responseOutput.innerHTML += "With " + requestObject.runs + " run: " + requestObject.requestTime + " seconds.<br />";
else
responseOutput.innerHTML += "With " + requestObject.runs + " runs: " + requestObject.requestTime + " seconds.<br />";
}
requestObject.running = 0;
if (allRequests.requests.length > (requestObject.arrayIndex+1))
sendRequestObject(allRequests, (requestObject.arrayIndex+1));
else
{
prepareFetchResults(allRequests);
prepareResults(allRequests);
resetPage();
}
}
}
function handleLatencyResponse(response)
{
var requestTime = (response.endTime - response.startTime)/1000;
if (gLatency > 0)
gLatency = (gLatency + requestTime) / 2;
else
gLatency = requestTime;
}
function stopRequests(allRequests)
{
gSend = 0;
for (var i=0;i<allRequests.requests.length;i++)
{
if (allRequests.requests[i].running)
{
for (var j=0;j<allRequests.requests[i].requestArray.length;j++)
AjaxTCR.comm.abortRequest(allRequests.requests[i].requestArray[j]);
resetPage();
break;
}
}
}
function sendRequestObject(allRequests, index)
{
if (gSend)
{
var requestObject = allRequests.requests[index];
requestObject.startTime = (new Date()).getTime();
requestObject.running = 1;
requestObject.requestArray = new Array();
for(var i=0;i<requestObject.requests.length;i++)
requestObject.requestArray.push(AjaxTCR.comm.sendRequest(requestObject.url, {payload: requestObject.requests[i], onSuccess:handleResponse, requestObject: requestObject, allRequests: allRequests}));
}
}
function prepareRequests(form)
{
gSend = 1;
document.getElementById("responseOutput").innerHTML = "";
var packetSize = parseInt(form.packetSize.options[form.packetSize.selectedIndex].value);
var chunking= form.chunking.options[form.chunking.selectedIndex].value;
var min = form.min.value;
if (isNaN(min) || min > 200 || min < 1)
{
alert("Error: Min must be a number between 1 and 200");
return false;
}
min = parseInt(min);
var max = form.max.value;
if (isNaN(max) || max > 200 || max < 0)
{
alert("Error: Max must be a number between 1 and 200.");
return false;
}
max = parseInt(max);
if (min > max)
{
alert("Error: Min must be less than or equal to max");
return false;
}
var fullruns = (max-min) + 1;
var allRequests = new Object();
allRequests.size = packetSize;
allRequests.chunked = chunking;
allRequests.start = min;
allRequests.end = max;
allRequests.requests = new Array();
var j = 0;
for (var i=min; i<=max; i++)
{
var requestObject = {};
requestObject.url = "https://ajaxref.com/ch6/payloadpartition.php";
requestObject.arrayIndex = j;
requestObject.runs = i;
requestObject.returned = 0;
requestObject.requests = new Array();
if (chunking == "equal")
{
var splitSize = Math.floor(packetSize/i);
var leftOver = packetSize%i;
for (var k=0;k<i;k++)
requestObject.requests.push("responsesize=" + splitSize);
}
else
{
var addedSoFar = 0;
for (var k=0;k<i;k++)
{
splitSize = generateRandom(i, k, packetSize, addedSoFar);
addedSoFar += splitSize;
requestObject.requests.push("responsesize=" + splitSize);
}
}
j++;
allRequests.requests.push(requestObject);
}
document.getElementById("spinner").style.display = "";
document.requestForm.requestButton.onclick = function () { stopRequests(allRequests); };
document.requestForm.requestButton.value = "Stop Test";
sendRequestObject(allRequests, 0);
}
function prepareResults(allRequests)
{
var size = allRequests.size;
var chunked= allRequests.chunked;
if (chunked == "equal")
chunked = 1;
else
chunked = 0;
var runs = allRequests.requests.length;
var payloadJson = new Object();
payloadJson.size = size;
payloadJson.chunked = chunked;
payloadJson.latency = Math.round(gLatency*10)/10;
payloadJson.times = new Array();
for (var i=0;i<runs;i++)
{
var times = new Object();
times.totaltime = allRequests.requests[i].requestTime;
times.runs = allRequests.requests[i].runs;
payloadJson.times.push(times);
}
var payload = AjaxTCR.data.encodeJSON(payloadJson);
AjaxTCR.comm.sendRequest("https://ajaxref.com/ch6/payloadpartition/storepayload.php", {payload: payload, method: "POST", requestContentType: "application/json"});
}
function prepareFetchResults(allRequests)
{
var size = allRequests.size;
var chunked= allRequests.chunked;
if (chunked == "equal")
chunked = 1;
else
chunked = 0;
var start = allRequests.start;
var end = allRequests.end;
var payload = "size=" + size + "&chunked=" + chunked + "&startrun=" + start + "&endrun=" + end + "&latency=" + Math.round(gLatency*10)/10;
AjaxTCR.comm.sendRequest("https://ajaxref.com/ch6/payloadpartition/getpayload.php", {payload: payload, onSuccess: handleResults, allRequests: allRequests});
}
function resetPage()
{
document.getElementById("spinner").style.display = "none";
document.requestForm.requestButton.onclick = function () { prepareRequests(this.form); };
document.requestForm.requestButton.value = "Start Test";
}
function generateRandom(totalRuns, runsSoFar, totalSize, sizeSoFar)
{
var size = 0;
var sizeLeft = totalSize - sizeSoFar;
var runsLeft = totalRuns - runsSoFar;
if (runsLeft == 1)
size = sizeLeft;
else
{
var randomFlag = (sizeLeft - runsLeft - 1);
size = Math.floor(Math.random()*randomFlag) + 1;
}
return size;
}
function calculateGraph(allRequests, averages)
{
var graph = document.getElementById("graph");
graph.innerHTML = "";
var canvas = document.createElement("canvas");
canvas.height = 300;
canvas.width = 1000;
canvas.id="graphcanvas";
graph.appendChild(canvas);
var runs = allRequests.requests.length;
var dataset = {};
dataset.CurrentResults = new Array(runs);
var min = 1000;
var max = 0;
var labels = new Array();
for (var i=0;i<runs;i++)
{
var thisLabel = {};
thisLabel.v = i;
thisLabel.label = allRequests.requests[i].runs;
labels.push(thisLabel);
dataset.CurrentResults[i] = new Array(2);
dataset.CurrentResults[i][0] = i;
dataset.CurrentResults[i][1] = allRequests.requests[i].requestTime;
min = Math.min(min, allRequests.requests[i].requestTime);
max = Math.max(max, allRequests.requests[i].requestTime);
}
dataset.Average = new Array();
for (var i=0;i<averages.length;i++)
{
dataset.Average[i] = new Array(2);
dataset.Average[i][0] = i;
dataset.Average[i][1] = Math.round(averages[i].time*1000)/1000;
}
var yTicks = Math.min(runs, 10);
var start = 0;
var diff = max-min;
var chunks = diff/yTicks;
if (min-chunks > 0)
start = min - chunks;
max += chunks;
var yLabels = new Array();
var lastVal = 0;
for (var j=0,i=start;i<=max;i+=chunks,j++)
{
var thisLabel = {};
var rounded = Math.round(i*1000)/1000;
thisLabel.v = rounded;
thisLabel.label = rounded;
lastVal = rounded;
yLabels.push(thisLabel);
}
var minMaxYAxis = [start, lastVal];
var options = {
padding: {left: 50, right: 0, top: 10, bottom: 30},
backgroundColor: '#f2f2f2',
colorScheme: new Hash({
'CurrentResults': '#1c4a7e',
'Average': '#bb5b3d'
}),
shouldFill: false,
xTicks: labels
};
var clear = false;
if (gLine)
{
gLine.reset();
clear = true;
}
else
gLine = new Plotr.LineChart('graphcanvas',options);
gLine.addDataset(dataset);
if (clear)
gLine.render('graphcanvas', options);
else
{
gLine.render();
gLine.addLegend($('lines_legend'));
}
if (averages.length > 0)
document.getElementById("lines_legend").style.display = "";
else
document.getElementById("lines_legend").style.display = "none";
}
window.onload = function ()
{
document.requestForm.requestButton.onclick = function () { prepareRequests(this.form); };
AjaxTCR.comm.sendRequest("https://ajaxref.com/ch6/specs.php", {payload: "responseSize=100", successCallback: handleLatencyResponse});
};
</head>
<body>
<div class="content">
<h1>Payload Partitioning Explorer</h1>
<form action="#" name="requestForm">
<fieldset>
<table width="100%">
<tr class="row">
<tr class="row">
<td width="125">Total Payload:</td>
<td>
<select name="packetSize">
<option value="50">50K</option>
<option value="100">100K</option>
<option value="250">250K</option>
<option value="500">500K</option>
<option value="1000">1000K</option>
</select>
</td>
</tr>
<tr class="row">
<td width="125">Request Range:</td>
<td>
Min: <input type="text" size="4" value="1" name="min" />
Max: <input type="text" size="4" value="10" name="max" />
</td>
</tr>
<tr class="row">
<td width="125">Chunking:</td>
<td>
<select name="chunking">
<option value="equal">Equal Chunk Sizes</option>
<option value="random">Random Chunk Sizes</option>
</select>
</td>
</tr>
</table>
</fieldset>
<br />
<input type="button" name="requestButton" id="requestButton" value="Start Test" /> <img src="spinner.gif" border="0" id="spinner" style="display:none;" />
</form>
<br />
</div>
<div id="response" class="results">
<div id="responseOutput"> </div>
</div><br /><br />
<fieldset id="lines_legend" style="display:none;">
</fieldset>
<div id="graph"></div><br />
</body>
</html>