1<head> 2 <title>Page Benchmark Options</title> 3 4 <script src="jst/util.js" type="text/javascript"></script> 5 <script src="jst/jsevalcontext.js" type="text/javascript"></script> 6 <script src="jst/jstemplate.js" type="text/javascript"></script> 7 <script src="jquery/jquery-1.4.2.min.js" type="text/javascript"></script> 8 <script src="jquery/jquery.flot.min.js" type="text/javascript"></script> 9 <script src="jquery/jquery.flot.dashes.js" type="text/javascript"></script> 10 <script src="util/table2CSV.js" type="text/javascript"></script> 11 <script src="util/sorttable.js" type="text/javascript"></script> 12 13<style> 14body { 15 font-size: 84%; 16 font-family: Helvetica, Arial, sans-serif; 17 padding: 0.75em; 18 margin: 0; 19 min-width: 45em; 20} 21 22h1 { 23 font-size: 110%; 24 font-weight: bold; 25 color: #4a8ee6; 26 letter-spacing: -1px; 27 padding: 0; 28 margin: 0; 29} 30 31div#header { 32 padding: 0.75em 1em; 33 padding-top: 0.6em; 34 padding-left: 10; 35 margin-bottom: 0.75em; 36 position: relative; 37 overflow: hidden; 38 background: #5296de; 39 background-size: 100%; 40 border: 1px solid #3a75bd; 41 border-radius: 6px; 42 color: white; 43 text-shadow: 0 0 2px black; 44} 45div#header h1 { 46 padding-left: 37px; 47 margin: 0; 48 display: inline; 49 color: white; 50} 51div#header p { 52 font-size: 84%; 53 font-style: italic; 54 padding: 0; 55 margin: 0; 56 color: white; 57 padding-left: 0.4em; 58 display: inline; 59} 60 61table.sortable { 62 font-size: 84%; 63 table-layout: fixed; 64} 65 66table.sortable:not([class*='filtered']) tr:nth-child(even) td:not([class*='filtered']) { 67 background: #eff3ff; 68} 69 70.nobg { 71 padding: 0 0.5em; 72 vertical-align: bottom; 73 font-weight: bold; 74 color: #315d94; 75 color: black; 76 text-align: center; 77} 78 79.bg{ 80 padding: 0 0.5em; 81 vertical-align: bottom; 82 font-weight: bold; 83 color: #315d94; 84 color: black; 85 text-align: center; 86 cursor: pointer; 87} 88 89.bg:hover { 90 background: #eff3aa; 91} 92 93.avg { 94 font-weight: bold; 95 text-align: center; 96} 97 98.data { 99 text-align: left; 100 white-space: nowrap; 101} 102 103.bggraph { 104 white-space: nowrap; 105} 106 107.file_input 108{ 109 position: absolute; 110 width: 140px; 111 height: 26px; 112 overflow: hidden; 113} 114 115.file_input_button 116{ 117 width: 140px; 118 position: absolute; 119 top: 0px; 120} 121 122.file_input_hidden 123{ 124 font-size: 25px; 125 position: absolute; 126 right: 0px; 127 top: 0px; 128 opacity: 0; 129} 130</style> 131 132<script> 133var max_sample = 0; 134 135Array.max = function(array) { 136 return Math.max.apply( Math, array ); 137} 138 139Array.min = function(array) { 140 return Math.min.apply( Math, array ); 141}; 142 143// Compute the average of an array, removing the min/max. 144Array.avg = function(array) { 145 var count = array.length; 146 var sum = 0; 147 var min = array[0]; 148 var max = array[0]; 149 for (var i = 0; i < count; i++) { 150 sum += array[i]; 151 if (array[i] < min) { 152 min = array[i]; 153 } 154 if (array[i] > max) { 155 max = array[i]; 156 } 157 } 158 if (count >= 3) { 159 sum = sum - min - max; 160 count -= 2; 161 } 162 return sum / count; 163} 164 165// Compute the standard deviation of an array 166Array.stddev = function(array) { 167 var count = array.length; 168 var mean = Array.avg(array); 169 var variance = 0; 170 for (var i = 0; i < count; i++) { 171 var deviation = mean - array[i]; 172 variance = variance + deviation * deviation; 173 } 174 variance = variance / count; 175 return Math.sqrt(variance); 176} 177 178function handleFileSelect(evt) { 179 var files = evt.target.files; 180 for (var i = 0, f; f = files[i]; i++) { 181 var reader = new FileReader(); 182 reader.onload = function(evt) { 183 document.getElementById("testurl").value = evt.target.result; 184 } 185 reader.readAsText(f); 186 }; 187} 188 189var THTAG = "th"; 190var TDTAG = "td"; 191var NONE_DISPLAY = "none"; 192var CELL_DISPLAY = "table-cell"; 193var BRIEF_VIEW = "Show More Details"; 194var FULL_VIEW = "Hide Details"; 195 196// Expand or shrink the result table. 197// Called when clicking button "Show More Details/Hide Details". 198function expand() { 199 if (document.getElementById("expand").value == BRIEF_VIEW) { 200 // From biref view to detailed view. 201 var headers = document.getElementsByTagName(THTAG); 202 var cells = document.getElementsByTagName(TDTAG); 203 204 // Display the hidden metrics (both headers and data cells). 205 for (var i = 0; i < headers.length; i++) { 206 if (headers[i].style.display == NONE_DISPLAY) { 207 headers[i].style.display = CELL_DISPLAY; 208 } 209 } 210 211 for (i = 0; i < cells.length; i++) { 212 if (cells[i].style.display == NONE_DISPLAY) { 213 cells[i].style.display = CELL_DISPLAY; 214 } 215 } 216 217 document.getElementById("expand").value = FULL_VIEW; 218 } else { 219 // From detailed view to brief view. 220 var headers = document.getElementsByTagName(THTAG); 221 var cells = document.getElementsByTagName(TDTAG); 222 223 // Hide some metrics. 224 for (var i = 0; i < headers.length; i++) { 225 if (headers[i].style.display == CELL_DISPLAY) { 226 headers[i].style.display = NONE_DISPLAY; 227 } 228 } 229 230 for (i = 0; i < cells.length; i++) { 231 if (cells[i].style.display == CELL_DISPLAY) { 232 cells[i].style.display = NONE_DISPLAY; 233 } 234 } 235 236 document.getElementById("expand").value = BRIEF_VIEW; 237 } 238 239 // Use cookie to store current expand/hide status. 240 var lastValue = document.getElementById("expand").value; 241 document.cookie = "lastValue=" + lastValue; 242} 243 244// Reloading the page causes table to shrink (default original status). 245// Cookie remembers last status of table (in terms of expanded or shrunk). 246function restoreTable() { 247 if (document.cookie == "lastValue=Hide Details") { 248 var headers = document.getElementsByTagName(THTAG); 249 var cells = document.getElementsByTagName(TDTAG); 250 251 for (var i = 0; i < headers.length; i++) { 252 if (headers[i].style.display == NONE_DISPLAY) { 253 headers[i].style.display = CELL_DISPLAY; 254 } 255 } 256 for (i = 0; i < cells.length; i++) { 257 if (cells[i].style.display == NONE_DISPLAY) { 258 cells[i].style.display = CELL_DISPLAY; 259 } 260 } 261 document.getElementById("expand").value = FULL_VIEW; 262 } 263} 264 265// A class to store the data to plot. 266function PData() { 267 this.xAxis = "Iteration(s)"; 268 this.yAxis = ""; 269 this.A = []; // Two data sets for comparison. 270 this.B = []; 271 this.avgA = []; // Avg value is plotted as a line. 272 this.avgB = []; 273 this.maxA = 0; 274 this.maxB = 0; 275 this.countA = 0; // Size of the data sets. 276 this.countB = 0; 277 278 this.setYAxis = function (str) { 279 this.yAxis = str; 280 } 281 282 this.setAvg = function (arr, cha) { 283 if (cha == 'A') { 284 var avgA = Array.avg(arr); 285 for (var i = 1; i <= this.countA; i++) { 286 this.avgA.push([i, avgA]); 287 } 288 } else if (cha == 'B') { 289 var avgB = Array.avg(arr); 290 for (var i = 1; i <= this.countB; i++) { 291 this.avgB.push([i, avgB]); 292 } 293 } 294 } 295 296 this.setMax = function (arr, cha) { 297 if (cha == 'A') { 298 this.maxA = Array.max(arr); 299 } else if (cha == 'B') { 300 this.maxB = Array.max(arr); 301 } 302 } 303 304 // Add an entry to the array. 305 this.addArr = function (val, cha) { 306 if (cha == 'A') { 307 this.countA++; 308 this.A.push([this.countA, val]); 309 } else if (cha == 'B') { 310 this.countB++; 311 this.B.push([this.countB, val]); 312 } 313 } 314 315 // Plot the graph at the specified place. 316 this.plot = function (placeholder) { 317 $.plot(placeholder, 318 [// Line A 319 { 320 data: this.A, 321 label: "A's " + this.yAxis + " in " + this.countA + " " + this.xAxis, 322 points: { 323 show: true 324 }, 325 lines: { 326 show: true 327 } 328 }, 329 330 // Line B 331 { 332 data: this.B, 333 label: "B's " + this.yAxis + " in " + this.countB + " " + this.xAxis, 334 points: { 335 show: true 336 }, 337 lines: { 338 show: true 339 } 340 }, 341 342 // Line avgA 343 { 344 data: this.avgA, 345 label: "A's avg " + this.yAxis, 346 dashes: { 347 show: true 348 } 349 }, 350 351 // Line avgB 352 { 353 data: this.avgB, 354 label: "B's avg " + this.yAxis, 355 dashes: { 356 show: true 357 } 358 }], 359 360 // Axis and legend setup. 361 { xaxis: { 362 max: this.countA > this.countB ? this.countA : this.countB, 363 tickSize: 1, 364 tickDecimals: 0 365 }, 366 yaxis: { 367 // Leave some space for legend. 368 max: this.maxA > this.maxB ? this.maxA * 1.5 : this.maxB * 1.5 369 }, 370 legend: { 371 backgroundOpacity: 0 372 } 373 }); 374 } 375} 376 377// Compare the selected metric of the two selected data sets. 378function compare() { 379 var checkboxArr = document.getElementsByName("checkboxArr"); 380 var radioArr = document.getElementsByName("radioArr"); 381 382 if (checkAmount(checkboxArr) != 2) { 383 alert("please select two rows to compare"); 384 return; 385 } 386 387 var rowIndexArr = getSelectedIndex(checkboxArr); 388 var colIndexArr = getSelectedIndex(radioArr); 389 // To this point, it is for sure that rowIndexArr has two elements 390 // while colIndexArr has one. 391 var selectedRowA = rowIndexArr[0]; 392 var selectedRowB = rowIndexArr[1]; 393 var selectedCol = colIndexArr[0]; 394 395 var extension = chrome.extension.getBackgroundPage(); 396 var data = extension.results.data; 397 var selectedA = getSelectedResults(data,selectedRowA,selectedCol); 398 var selectedB = getSelectedResults(data,selectedRowB,selectedCol); 399 var yAxis = getMetricName(selectedCol); 400 401 // Indicate A and B on selected rows. 402 checkboxArr[selectedRowA].parentElement.firstChild.data = "A"; 403 checkboxArr[selectedRowB].parentElement.firstChild.data = "B"; 404 405 plot(selectedA, selectedB, yAxis); 406} 407 408// Show the comparison graph. 409function plot(A, B, axis) { 410 var plotData = new PData(); 411 412 plotData.setYAxis(axis); 413 for (var i = 0; i < A.length; i++) { 414 plotData.addArr(A[i],'A'); 415 } 416 for (var i = 0; i < B.length; i++) { 417 plotData.addArr(B[i],'B'); 418 } 419 plotData.setAvg(A,'A'); 420 plotData.setAvg(B,'B'); 421 plotData.setMax(A,'A'); 422 plotData.setMax(B,'B'); 423 424 var placeholder = document.getElementById("placeholder"); 425 placeholder.style.display = ""; 426 plotData.plot(placeholder); 427} 428 429var METRIC = {"STARTLOAD": 0, "COMMITLOAD": 1, "DOCLOAD": 2, "PAINT": 3, 430 "TOTAL": 4, "REQUESTS": 5, "CONNECTS": 6, "READKB": 7, 431 "WRITEKB": 8, "READKBPS": 9, "WRITEKBPS": 10}; 432 433// Retrieve the metric name from index. 434function getMetricName (index) { 435 switch (index) { 436 case METRIC.STARTLOAD: 437 return "Start Load Time"; 438 case METRIC.COMMITLOAD: 439 return "Commit Load Time"; 440 case METRIC.DOCLOAD: 441 return "Doc Load Time"; 442 case METRIC.PAINT: 443 return "Paint Time"; 444 case METRIC.TOTAL: 445 return "Total Load Time"; 446 case METRIC.REQUESTS: 447 return "# Requests"; 448 case METRIC.CONNECTS: 449 return "# Connects"; 450 case METRIC.READKB: 451 return "Read KB"; 452 case METRIC.WRITEKB: 453 return "Write KB"; 454 case METRIC.READKBPS: 455 return "Read KBps"; 456 case METRIC.WRITEKBPS: 457 return "Write KBps"; 458 default: 459 return ""; 460 } 461} 462 463// Get the results with a specific row (data set) and column (metric). 464function getSelectedResults(arr, rowIndex, colIndex) { 465 switch (colIndex) { 466 case METRIC.STARTLOAD: 467 return arr[rowIndex].startLoadResults; 468 case METRIC.COMMITLOAD: 469 return arr[rowIndex].commitLoadResults; 470 case METRIC.DOCLOAD: 471 return arr[rowIndex].docLoadResults; 472 case METRIC.PAINT: 473 return arr[rowIndex].paintResults; 474 case METRIC.TOTAL: 475 return arr[rowIndex].totalResults; 476 case METRIC.REQUESTS: 477 return arr[rowIndex].requests; 478 case METRIC.CONNECTS: 479 return arr[rowIndex].connects; 480 case METRIC.READKB: 481 return arr[rowIndex].KbytesRead; 482 case METRIC.WRITEKB: 483 return arr[rowIndex].KbytesWritten; 484 case METRIC.READKBPS: 485 return arr[rowIndex].readbpsResults; 486 case METRIC.WRITEKBPS: 487 return arr[rowIndex].writebpsResults; 488 default: 489 return undefined; 490 } 491} 492 493// Ensure only two data sets (rows) are selected. 494function checkAmount(arr) { 495 var amount = 0; 496 for (var i = 0; i < arr.length; i++) { 497 if (arr[i].checked) { 498 amount++; 499 } 500 } 501 return amount; 502} 503 504// Get the index of selected row or column. 505function getSelectedIndex(arr) { 506 var selectedArr = new Array(); 507 for (var i = 0; i < arr.length; i++) { 508 if(arr[i].checked) { 509 selectedArr.push(i); 510 } 511 } 512 return selectedArr; 513} 514 515// Repaint or hide the chart. 516function updateChart(caller) { 517 var placeholder = document.getElementById("placeholder"); 518 if (caller.type == "radio") { 519 // Other radio button is clicked. 520 if (placeholder.style.display == "") { 521 compare(); 522 } 523 } else { 524 // Other checkbox or clearing results is clicked. 525 if (placeholder.style.display == "") { 526 placeholder.style.display = "none"; 527 } 528 } 529} 530 531// Clear indicators besides checkbox. 532function clearIndicator () { 533 var checkboxArr = document.getElementsByName("checkboxArr"); 534 for (var i = 0; i < checkboxArr.length; i++) { 535 checkboxArr[i].parentElement.firstChild.data = ""; 536 } 537} 538 539// Enable/Disable buttons according to checkbox change. 540function checkSelected () { 541 var checkboxArr = document.getElementsByName("checkboxArr"); 542 if (checkAmount(checkboxArr) !=0) { 543 document.getElementById("clearSelected").disabled = false; 544 document.getElementById("compare").disabled = false; 545 } else { 546 document.getElementById("clearSelected").disabled = true; 547 document.getElementById("compare").disabled = true; 548 } 549} 550 551// Object to summarize everything 552var totals = {}; 553 554// Compute the results for a data set. 555function computeDisplayResults(data) { 556 var count = data.data.length; 557 for (var i = 0; i < count; i++) { 558 var obj = data.data[i]; 559 obj.displayTime = setDisplayTime(obj.timestamp); 560 var resultList = obj.totalResults; 561 obj.mean = Array.avg(resultList); 562 obj.stddev = Array.stddev(resultList); 563 obj.stderr = obj.stddev / Math.sqrt(obj.iterations); 564 var ci = 1.96 * obj.stderr; 565 obj.cihigh = obj.mean + ci; 566 obj.cilow = obj.mean - ci; 567 obj.min = Array.min(resultList); 568 obj.max = Array.max(resultList); 569 obj.readbps = Array.avg(obj.readbpsResults); 570 obj.writebps = Array.avg(obj.writebpsResults); 571 obj.readKB = Array.avg(obj.KbytesRead); 572 obj.writeKB = Array.avg(obj.KbytesWritten); 573 obj.paintMean = Array.avg(obj.paintResults); 574 obj.startLoadMean = Array.avg(obj.startLoadResults); 575 obj.commitLoadMean = Array.avg(obj.commitLoadResults); 576 obj.docLoadMean = Array.avg(obj.docLoadResults); 577 578 obj.displayRequests = Array.avg(obj.requests); 579 obj.displayConnects = Array.avg(obj.connects); 580 obj.displaySpdySessions = Array.avg(obj.spdySessions); 581 582 obj.displayDomNum = obj.domNum; 583 obj.displayMaxDepth = obj.maxDepth; 584 obj.displayMinDepth = obj.minDepth; 585 obj.displayAvgDepth = obj.avgDepth; 586 } 587 return count; 588} 589 590// Convert timestamp to readable string. 591function setDisplayTime(ts) { 592 var year = ts.getFullYear(); 593 var mon = ts.getMonth()+1; 594 var date = ts.getDate(); 595 var hrs = ts.getHours(); 596 var mins = ts.getMinutes(); 597 var secs = ts.getSeconds(); 598 599 mon = ( mon < 10 ? "0" : "" ) + mon; 600 date = ( date < 10 ? "0" : "" ) + date; 601 mins = ( mins < 10 ? "0" : "" ) + mins; 602 secs = ( secs < 10 ? "0" : "" ) + secs; 603 604 return (year + "/" + mon + "/" + date + " " + hrs + ":" + mins + ":" + secs); 605} 606 607// Subtract the results from two data sets. 608// This function could be smarter about what it subtracts, 609// for now it just subtracts everything. 610// Returns true if it was able to compare the two data sets. 611function subtractData(data, baseline) { 612 var count = data.data.length; 613 if (baseline.data.length != count) { 614 return false; 615 } 616 for (var i = 0; i < count; i++) { 617 var obj = data.data[i]; 618 var obj2 = baseline.data[i]; 619 620 // The data sets are different. 621 if (obj.url != obj2.url || 622 obj.iterations != obj2.iterations) { 623 return false; 624 } 625 626 obj.mean -= obj2.mean; 627 obj.stddev -= obj2.stddev; 628 obj.min -= obj2.min; 629 obj.max -= obj2.max; 630 obj.readbps -= obj2.readbps; 631 obj.writebps -= obj2.writebps; 632 obj.readKB -= obj2.readKB; 633 obj.writeKB -= obj2.writeKB; 634 obj.paintMean -= obj2.paintMean; 635 obj.startLoadMean -= obj2.startLoadMean; 636 obj.commitLoadMean -= obj2.commitLoadMean; 637 obj.docLoadMean -= obj2.docLoadMean; 638 639 obj.displayRequests -= obj2.displayRequests; 640 obj.displayConnects -= obj2.displayConnects; 641 obj.displaySpdySessions -= obj2.displaySpdySessions; 642 } 643 return true; 644} 645 646// Compute totals based on a data set. 647function computeTotals(data) { 648 var count = data.data.length; 649 for (var i = 0; i < count; i++) { 650 var obj = data.data[i]; 651 totals.mean += obj.mean; 652 totals.paintMean += obj.paintMean; 653 totals.startLoadMean += obj.startLoadMean; 654 totals.commitLoadMean += obj.commitLoadMean; 655 totals.docLoadMean += obj.docLoadMean; 656 } 657} 658 659// Compute results for the data with an optional baseline. 660// If |baseline| is undefined, will compute the results of this 661// run. Otherwise, computes the diff between this data and the baseline. 662function computeResults(data, baseline) { 663 totals = {}; 664 totals.mean = 0; 665 totals.paintMean = 0; 666 totals.startLoadMean = 0; 667 totals.commitLoadMean = 0; 668 totals.docLoadMean = 0; 669 670 var count = computeDisplayResults(data); 671 672 if (baseline) { 673 computeDisplayResults(baseline); 674 if (!subtractData(data, baseline)) { 675 alert("These data sets are different"); 676 document.getElementById("baseline").value = ""; 677 return; 678 } 679 } 680 681 computeTotals(data); 682 totals.url = "(" + count + " urls)"; 683 if (count > 0) { 684 totals.mean /= count; 685 totals.paintMean /= count; 686 totals.startLoadMean /= count; 687 totals.commitLoadMean /= count; 688 totals.docLoadMean /= count; 689 } 690 691 // Find the biggest average for our bar graph. 692 max_sample = 0; 693 for (var i = 0; i < data.data.length; i++) { 694 if (data.data[i].max > max_sample) { 695 max_sample = data.data[i].mean; 696 } 697 } 698} 699 700function jsinit() { 701 var extension = chrome.extension.getBackgroundPage(); 702 703 // Run the template to show results 704 var data = extension.results; 705 706 // Get the baseline results 707 var elt = document.getElementById("baseline"); 708 var baseline_json = document.getElementById("baseline").value; 709 var baseline; 710 if (baseline_json) { 711 try { 712 baseline = JSON.parse(baseline_json); 713 } catch (e) { 714 alert("JSON parse error: " + e); 715 } 716 } 717 718 // Compute 719 computeResults(data, baseline); 720 721 var context = new JsEvalContext(data); 722 context.setVariable('$width', 0); 723 context.setVariable('$samples', 0); 724 var template = document.getElementById("t"); 725 jstProcess(context, template); 726 727 // Set the options 728 document.getElementById("iterations").value = extension.iterations; 729 document.getElementById("clearconns").checked = extension.clearConnections; 730 document.getElementById("clearcache").checked = extension.clearCache; 731 document.getElementById("enablespdy").checked = extension.enableSpdy; 732 setUrl(extension.testUrl); 733 734 if (!baseline) { 735 var json_data = JSON.stringify(data); 736 document.getElementById("json").value = json_data; 737 } 738 739 // Activate loading Urls from local file. 740 document.getElementById('files').addEventListener('change', 741 handleFileSelect, false); 742} 743 744function getWidth(mean, obj) { 745 var kMinWidth = 200; 746 var max_width = obj.offsetWidth; 747 if (max_width < kMinWidth) { 748 max_width = kMinWidth; 749 } 750 return Math.floor(max_width * (mean / max_sample)); 751} 752 753// Apply configuration back to our extension 754function config() { 755 var extension = chrome.extension.getBackgroundPage(); 756 var iterations = parseInt(document.getElementById("iterations").value); 757 var clearConnections = document.getElementById("clearconns").checked; 758 var clearCache = document.getElementById("clearcache").checked; 759 var enableSpdy = document.getElementById("enablespdy").checked; 760 if (iterations > 0) { 761 extension.iterations = iterations; 762 extension.clearConnections = clearConnections; 763 extension.clearCache = clearCache; 764 extension.enableSpdy = enableSpdy; 765 } 766} 767 768// Set the url in the benchmark url box. 769function setUrl(url) { 770 document.getElementById("testurl").value = url; 771} 772 773// Start the benchmark. 774function run() { 775 if (!chrome.benchmarking) { 776 alert("Warning: Looks like you forgot to run chrome with " + 777 " --enable-benchmarking set."); 778 return; 779 } 780 var extension = chrome.extension.getBackgroundPage(); 781 var testUrl = document.getElementById("testurl").value; 782 extension.testUrl = testUrl; 783 extension.run(); 784} 785 786function showConfirm() { 787 var r = confirm("Are you sure to clear results?"); 788 if (r) { 789 // Find out the event source element. 790 var evtSrc = window.event.srcElement; 791 if (evtSrc.value == "Clear Selected") { 792 clearSelected(); 793 } else if (evtSrc.value == "Clear All") { 794 clearResults(); 795 } 796 } 797} 798 799// Clear the selected results 800function clearSelected() { 801 var extension = chrome.extension.getBackgroundPage(); 802 var checkboxArr = document.getElementsByName("checkboxArr"); 803 var rowIndexArr = getSelectedIndex(checkboxArr); 804 var currIndex; 805 for (var i = 0; i < rowIndexArr.length; i++) { 806 currIndex = rowIndexArr[i]; 807 // Update the index of the original row in the modified array. 808 currIndex -= i; 809 extension.results.data.splice(currIndex, 1); 810 document.location.reload(true); 811 updateChart(this); 812 jsinit(); 813 } 814} 815 816// Clear all the results 817function clearResults() { 818 var extension = chrome.extension.getBackgroundPage(); 819 extension.results = {}; 820 extension.results.data = new Array(); 821 document.getElementById("json").value = ""; 822 document.getElementById("baseline").value = ""; 823 updateChart(this); 824 jsinit(); 825} 826 827// Export html table into CSV format. 828function export() { 829 var checkboxArr = document.getElementsByName("checkboxArr"); 830 var rowNum = checkboxArr.length + 1; // # of data rows plus total-stats row. 831 $('#t').table2CSV(rowNum); 832} 833 834// Toggle display of an element 835function toggle(id) { 836 var elt = document.getElementById(id); 837 if (elt.style.display == "none") { 838 elt.style.display = "block"; 839 } else { 840 elt.style.display = "none"; 841 } 842} 843</script> 844 845</head> 846 847<body onload="jsinit(); restoreTable()"> 848 849<h1><div id="header">Page Benchmark Results</div></h1> 850 851<h1>Configuration <a href="http://sites.google.com/a/chromium.org/dev/chrome-benchmarking-extension" target="_blank" style="float:right"><font size="4%">Help</font></a></h1> 852 853<span>Iterations</span> 854<input id="iterations" type="text" style="text-align:right" size="4"> 855Clear Connections?<input id="clearconns" type="checkbox"> 856Clear Cache?<input id="clearcache" type="checkbox"> 857Enable Spdy?<input id="enablespdy" type="checkbox"> 858<br> 859<span>URLs to load</span> <input type="text" id="testurl" size="80"> 860<span class="file_input"> 861<input class="file_input_button" type="button" value="Load URLs From File" /> 862<input class="file_input_hidden" type="file" id="files" name="files[]" multiple /> 863</span> 864<form onsubmit="config();run()"> 865<input type="submit" value="Run"> 866</form> 867<p> 868 869<h1>Results</h1> 870 871<input id="expand" type="button" value="Show More Details" onclick="expand()"> 872<input id="clearSelected" type="button" value="Clear Selected" disabled="true" onclick="showConfirm()"> 873<input id="clearAll" type="button" value="Clear All" onclick="showConfirm()"> 874<input type="button" value="Export As .csv" onclick="export()"> 875<table id="t" class="sortable" width="100%"> 876 <tr> 877 <th width=35 class="nobg"></th> 878 <th width=215 class="nobg">url</th> 879 <th width=110 class="nobg" style="display:none">timestamp</th> 880 <th width=50 class="nobg">iterations</th> 881 <th width=50 class="nobg">via spdy</th> 882 <th width=50 class="bg" style="display:none">start load mean</th> 883 <th width=50 class="bg" style="display:none">commit load mean</th> 884 <th width=50 class="bg">doc load mean</th> 885 <th width=50 class="bg">paint mean</th> 886 <th width=50 class="bg">total load mean</th> 887 <th width=50 class="bg">stddev</th> 888 <th width=50 class="bg" style="display:none">stderr</th> 889 <th width=50 class="bg" style="display:none">95% CI-low</th> 890 <th width=50 class="bg" style="display:none">95% CI-high</th> 891 <th width=50 class="bg" style="display:none">min</th> 892 <th width=50 class="bg" style="display:none">max</th> 893 <th width=60 class="bg" style="display:none"># Requests</th> 894 <th width=60 class="bg" style="display:none"># Connects</th> 895 <th width=50 class="bg" style="display:none"># SPDY Sessions</th> 896 <th width=50 class="bg" style="display:none">Read KB</th> 897 <th width=50 class="bg" style="display:none">Write KB</th> 898 <th width=50 class="bg">Read KBps</th> 899 <th width=50 class="bg">Write KBps</th> 900 <th width=50 class="bg"># DOM</th> 901 <th width=70 class="bg" style="display:none">max DOM depth</th> 902 <th width=30 class="bg" style="display:none">min</th> 903 <th width=30 class="bg" style="display:none">avg</th> 904 <th samples class="nobg" style="display:none">total loan time samples</th> 905 </tr> 906 907 <tr id="t.total" jsselect="totals"> 908 <td class="avg" jseval="1"></td> 909 <td class="url">TOTALS <span jscontent="url"></span></td> 910 <td class="avg" style="display:none"></td> 911 <td class="avg" jseval="1"></td> 912 <td class="avg" jseval="1"></td> 913 <td class="avg" style="display:none"><span jseval="val = startLoadMean.toFixed(1)" jscontent="val"></span></td> 914 <td class="avg" style="display:none"><span jseval="val = commitLoadMean.toFixed(1)" jscontent="val"></span></td> 915 <td class="avg"><span jseval="val = docLoadMean.toFixed(1)" jscontent="val"></span></td> 916 <td class="avg"><span jseval="val = paintMean.toFixed(1)" jscontent="val"></span></td> 917 <td class="avg"><span jseval="val = mean.toFixed(1)" jscontent="val"></span></td> 918 <td class="avg" jseval="1"></td> 919 <td class="avg" jseval="1"></td> 920 <td class="avg" jseval="1"></td> 921 <td class="avg" jseval="1"></td> 922 <td class="avg" jseval="1"></td> 923 <td class="avg" jseval="1"></td> 924 <td class="avg" jseval="1"></td> 925 <td class="avg" jseval="1"></td> 926 <td class="avg" jseval="1"></td> 927 <td class="avg" jseval="1"></td> 928 <td class="avg" jseval="1"></td> 929 <td class="avg" jseval="1"></td> 930 <td class="avg" jseval="1"></td> 931 <td class="avg" jseval="1"></td> 932 <td class="avg" jseval="1"></td> 933 <td class="avg" jseval="1"></td> 934 <td class="avg" jseval="1"></td> 935 <td class="data"></td> 936 </tr> 937 938 <tr jsselect="data"> 939 <td align=right> <input type="checkbox" name="checkboxArr" onclick="updateChart(this);clearIndicator();checkSelected()"></td> 940 <td class="url" jseval="$width = getWidth($this.mean, this); url.length > 40 ? $suburl = url.substring(0,27) + '...' + url.substring(url.length-10, url.length) : $suburl=url"><div jsvalues=".style.width:$width" class="bggraph"><a jsvalues="href:$this.url" jscontent="$suburl"></a></div></td> 941 <td class="avg" style="display:none" jseval="val = displayTime" jscontent="val"></td> 942 <td class="avg" jseval="val = iterations" jscontent="val"></td> 943 <td class="avg" jseval="val = viaSpdy" jscontent="val"></td> 944 <td class="avg" style="display:none" jseval="val = startLoadMean.toFixed(1)" jscontent="val"></td> 945 <td class="avg" style="display:none" jseval="val = commitLoadMean.toFixed(1)" jscontent="val"></td> 946 <td class="avg" jseval="val = docLoadMean.toFixed(1)" jscontent="val"></td> 947 <td class="avg" jseval="val = paintMean.toFixed(1)" jscontent="val"></td> 948 <td class="avg" jseval="val = mean.toFixed(1)" jscontent="val"></td> 949 <td class="avg" jseval="val = stddev.toFixed(1)" jscontent="val"></td> 950 <td class="avg" style="display:none" jseval="val = stderr.toFixed(1)" jscontent="val"></td> 951 <td class="avg" style="display:none" jseval="val = cilow.toFixed(1)" jscontent="val"></td> 952 <td class="avg" style="display:none" jseval="val = cihigh.toFixed(1)" jscontent="val"></td> 953 <td class="avg" style="display:none" jseval="val = min.toFixed(1)" jscontent="val"></td> 954 <td class="avg" style="display:none" jseval="val = max.toFixed(1)" jscontent="val"></td> 955 <td class="avg" style="display:none" jseval="val = displayRequests.toFixed(1)" jscontent="val"></td> 956 <td class="avg" style="display:none" jseval="val = displayConnects.toFixed(1)" jscontent="val"></td> 957 <td class="avg" style="display:none" jseval="val = displaySpdySessions.toFixed(1)" jscontent="val"></td> 958 <td class="avg" style="display:none" jseval="val = readKB.toFixed(1)" jscontent="val"></td> 959 <td class="avg" style="display:none" jseval="val = writeKB.toFixed(1)" jscontent="val"></td> 960 <td class="avg" jseval="val = readbps.toFixed(1)" jscontent="val"></td> 961 <td class="avg" jseval="val = writebps.toFixed(1)" jscontent="val"></td> 962 <td class="avg" jseval="val = displayDomNum" jscontent="val"></td> 963 <td class="avg" style="display:none" jseval="val = displayMaxDepth" jscontent="val"></td> 964 <td class="avg" style="display:none" jseval="val = displayMinDepth" jscontent="val"></td> 965 <td class="avg" style="display:none" jseval="val = displayAvgDepth.toFixed(1)" jscontent="val"></td> 966 <td class="data" style="display:none"><span jsselect="totalResults"><span jscontent="$this"></span>,</span> </td> 967 </tr> 968 <tr jsdisplay="data.length == 0"> 969 <td colspan=2>No tests have been run yet.</td> 970 </tr> 971 <tr jsdisplay="data.length > 1"> 972 <td width=25 jseval="1"></td> 973 <td class="url" jseval="1"></td> 974 <td class="avg" style="display:none" jseval="1"></td> 975 <td class="avg" jseval="1"></td> 976 <td class="avg" jseval="1"></td> 977 <td class="avg" style="display:none"><input name="radioArr" type="radio" onclick="updateChart(this)"> </td> 978 <td class="avg" style="display:none"><input name="radioArr" type="radio" onclick="updateChart(this)"></td> 979 <td class="avg"><input name="radioArr" type="radio" onclick="updateChart(this)"></td> 980 <td class="avg"><input name="radioArr" type="radio" onclick="updateChart(this)"></td> 981 <td class="avg"><input name="radioArr" type="radio" onclick="updateChart(this)" checked></td> 982 <td class="avg" jseval="1"></td> 983 <td class="avg" style="display:none" jseval="1"></td> 984 <td class="avg" style="display:none" jseval="1"></td> 985 <td class="avg" style="display:none" jseval="1"></td> 986 <td class="avg" style="display:none" jseval="1"></td> 987 <td class="avg" style="display:none" jseval="1"></td> 988 <td class="avg" style="display:none"><input name="radioArr" type="radio" onclick="updateChart(this)"></td> 989 <td class="avg" style="display:none"><input name="radioArr" type="radio" onclick="updateChart(this)"></td> 990 <td class="avg" style="display:none" jseval="1"></td> 991 <td class="avg" style="display:none"><input name="radioArr" type="radio" onclick="updateChart(this)"></td> 992 <td class="avg" style="display:none"><input name="radioArr" type="radio" onclick="updateChart(this)"></td> 993 <td class="avg"><input name="radioArr" type="radio" onclick="updateChart(this)"></td> 994 <td class="avg"><input name="radioArr" type="radio" onclick="updateChart(this)"></td> 995 </tr> 996 <tr jsdisplay="data.length > 1"> 997 <td> <input id="compare" type="button" value="Compare" disabled="true" onclick="compare()"></td> 998 </tr> 999</table> 1000<hr> 1001<center> 1002<div id="placeholder" style="width:430px;height:230px;display:none">graph place</div> 1003</center> 1004<span onclick="toggle('json')">JSON data</span><br> 1005<textarea style="display:none" type=text id=json rows=10 cols=50></textarea><p> 1006 1007<span onclick="toggle('baseline')">COMPARE to</span><br> 1008<textarea style="display:none" type=text id=baseline rows=10 cols=50 1009onchange="jsinit()"></textarea><p> 1010</body> 1011