Skip to content

banner ajax
The Complete Reference: Ajax

Examples: Payload Explorer

Payload Partitioning Explorer

Total Payload:
Request Range: Min: Max:
Chunking:

 

 



<!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" />
<style type="text/css">
 
    #responseOutput {
        height:200px;
        overflow:auto;
    }
    
    #lines_legend{
        margin-left:50px;
        width:930px;
    }
</style>
<script type="text/javascript" src="https://ajaxref.com/ch6/ajaxtcr.js" >
</script>
<script type="text/javascript" src="https://ajaxref.com/lib/prototype1.5.1/prototype.js" >
</script>
<script type="text/javascript" src="https://ajaxref.com/lib/excanvas/excanvas.js" >
</script>
<script type="text/javascript" src="https://ajaxref.com/lib/plotr/plotr.js" >
</script>
<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)
    {
        //calculate time
        var endTime = (new Date()).getTime();
        requestObject.requestTime = (endTime - requestObject.startTime)/1000;
        
        //print message
        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;
        //either call next request or reset page
        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;
    
    //calculate dataset
    var dataset = {};
    dataset.CurrentResults = new Array(runs);
    
    //calculate the lables
    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;
    }
 
    //calculate y labels because it is a bit buggy in library
    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];
    
    // Define options.
    var options = {
        
        padding: {left: 50, right: 0, top: 10, bottom: 30},
        
        // Background color to render.
        backgroundColor: '#f2f2f2',
 
        
        // Set a custom colorScheme
        colorScheme: new Hash({
            'CurrentResults': '#1c4a7e',
            'Average': '#bb5b3d'
        }),
        
        shouldFill: false,
 
        xTicks: labels
        
        //yTicks: yLabels,
        
        //yAxis: minMaxYAxis
        
        
    };
 
    // Instantiate a new LineCart.
    var clear = false;
    if (gLine)
    {
        gLine.reset();
        clear = true;
    }
    else
        gLine = new Plotr.LineChart('graphcanvas',options);
        
    // Add a dataset to it.
    gLine.addDataset(dataset);
    // Render it.
    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});
};
</script>
 
</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" /> &nbsp;<img src="spinner.gif" border="0" id="spinner" style="display:none;" />
</form>
<br />
</div>
<div id="response" class="results">
    <div id="responseOutput">&nbsp;</div>
</div><br /><br />
<fieldset id="lines_legend" style="display:none;">
    
</fieldset>
<div id="graph"></div><br />
 
</body>
</html>