| 1 | <!DOCTYPE html> |
| 2 | <html> |
| 3 | <head> |
| 4 | <title>Benchmarking for Plots with Many Points</title> |
| 5 | <!-- |
| 6 | For production (minified) code, use: |
| 7 | <script type="text/javascript" src="dygraph-combined.js"></script> |
| 8 | --> |
| 9 | <script type="text/javascript" src="../dygraph-dev.js"></script> |
| 10 | |
| 11 | </head> |
| 12 | <body> |
| 13 | <p>Plot which can be easily generated with different numbers of points for |
| 14 | benchmarking/profiling and improving performance of dygraphs.</p> |
| 15 | <div id='parameters'> |
| 16 | <p>Data to plot: |
| 17 | <input type="radio" id="sine" name="group1" value="sine" |
| 18 | onclick="setDataType(this);" checked> sinusoid function |
| 19 | <input type="radio" id="rand" name="group1" value="rand" |
| 20 | onclick="setDataType(this);"> random points <br></p> |
| 21 | <p>Timestamps: |
| 22 | <input type="radio" id="aligned" name="timestamps" value="aligned" checked> aligned |
| 23 | <input type="radio" id="unaligned" name="timestamps" value="unaligned"> unaligned |
| 24 | </p> |
| 25 | <p>x-axis type: |
| 26 | <input type="radio" id="numeric" name="x-axis-type" value="numeric" onclick="setXAxisType(this)" checked> numeric |
| 27 | <input type="radio" id="dates" name="x-axis-type" value="date" onclick="setXAxisType(this)"> date/time |
| 28 | <p><input type="checkbox" id="fill"><label for="fill"> Fill?</label></p> |
| 29 | <p>Number of points per series (points): |
| 30 | <input type="text" id="points" size="20"></p> |
| 31 | <p>Number of series (series): |
| 32 | <input type="text" id="series" size="20"></p> |
| 33 | <p>Roll period (in points, rollPeriod): |
| 34 | <input type="text" id="rollPeriod" size="20"></p> |
| 35 | <p>Repetitions (repititions): |
| 36 | <input type="text" id="repetitions" size="20"></p> |
| 37 | <input type="button" value="Go!" onclick="updatePlot();"> |
| 38 | </div> |
| 39 | <br> |
| 40 | <br> |
| 41 | <div id="plot"></div> |
| 42 | <div id="message"></div> |
| 43 | <div id="metrics"></div> |
| 44 | <div id="metaperformance"></div> |
| 45 | |
| 46 | <script type="text/javascript"> |
| 47 | var graph = null; |
| 48 | var metrics = null; |
| 49 | var dataType = "sine"; |
| 50 | var timestamps = "aligned"; |
| 51 | var numRuns = 0; |
| 52 | |
| 53 | var durations = []; |
| 54 | updatePlot = function() { |
| 55 | document.getElementById('message').innerHTML = ""; |
| 56 | var plotDiv = document.getElementById('plot'); |
| 57 | plotDiv.innerHTML = 'Redrawing...'; |
| 58 | var numeric = document.getElementById('numeric').checked; |
| 59 | var numPoints = |
| 60 | parseInt(document.getElementById('points').value); |
| 61 | var numSeries = |
| 62 | parseInt(document.getElementById('series').value); |
| 63 | var repetitions = |
| 64 | parseInt(document.getElementById('repetitions').value); |
| 65 | |
| 66 | var data = []; |
| 67 | var xmin = numeric ? 0.0 : Date.parse("2014/01/01"); |
| 68 | var xmax = numeric ? 2.0 * Math.PI : Date.parse("2014/12/31"); |
| 69 | var adj = .5; |
| 70 | var delta = (xmax - xmin) / (numPoints - 1); |
| 71 | var unalignmentDelta = delta / numSeries; |
| 72 | |
| 73 | for (var i = 0; i < numPoints; ++i) { |
| 74 | var x = xmin + delta * i; |
| 75 | var elem = [ x ]; |
| 76 | for (var j = 0; j < numSeries; j++) { |
| 77 | var y; |
| 78 | if (dataType == "rand") { |
| 79 | y = Math.pow(Math.random() - Math.random(), 7); |
| 80 | } else { |
| 81 | y = Math.sin(x + (j * adj)); |
| 82 | } |
| 83 | elem.push(y); |
| 84 | } |
| 85 | if (timestamps == "aligned") { |
| 86 | data[i] = elem; |
| 87 | } else { |
| 88 | for (var j = 0; j < numSeries; j++) { |
| 89 | var elemCopy = elem.slice(0); |
| 90 | elemCopy[0] += unalignmentDelta * j; |
| 91 | data[i*numSeries + j] = elemCopy; |
| 92 | } |
| 93 | } |
| 94 | if (!numeric) data[i][0] = new Date(data[i][0]); |
| 95 | } |
| 96 | var labels = [ "x" ]; |
| 97 | for (var j = 0; j < numSeries; j++) { |
| 98 | labels.push("data-set-" + j); |
| 99 | } |
| 100 | var rollPeriod = parseInt( |
| 101 | document.getElementById('rollPeriod').value); |
| 102 | var opts = {labels: labels, rollPeriod: rollPeriod, timingName: "x"}; |
| 103 | opts['fillGraph'] = document.getElementById('fill').checked; |
| 104 | var millisecondss = []; |
| 105 | for (var i = 0; i < repetitions; i++) { |
| 106 | if (graph != null) { |
| 107 | graph.destroy(); // release memory from prior graph. |
| 108 | } |
| 109 | var start = new Date(); |
| 110 | graph = new Dygraph(plotDiv, data, opts); |
| 111 | var end = new Date(); |
| 112 | durations.push([numRuns++, end - start]); |
| 113 | millisecondss.push(end - start); |
| 114 | } |
| 115 | if (repetitions == 1) { |
| 116 | document.getElementById('message').innerHTML = |
| 117 | "completed in " + (end - start) + " milliseconds."; |
| 118 | } else { |
| 119 | var avg = 0; |
| 120 | for (var i = 0; i < millisecondss.length; i++) { |
| 121 | avg+=millisecondss[i]; |
| 122 | } |
| 123 | avg/=millisecondss.length; |
| 124 | document.getElementById('message').innerHTML = |
| 125 | "Durations: " + millisecondss + "<br>Average: " + avg; |
| 126 | } |
| 127 | |
| 128 | if (durations.length > 0) { |
| 129 | var start2 = new Date(); |
| 130 | if (!metrics) { |
| 131 | metrics = new Dygraph( |
| 132 | document.getElementById('metrics'), |
| 133 | durations, |
| 134 | { |
| 135 | highlightCircleSize: 4, |
| 136 | labels: [ "Date", "ms" ] |
| 137 | }); |
| 138 | } else { |
| 139 | metrics.updateOptions({file: durations}); |
| 140 | } |
| 141 | var end2 = new Date(); |
| 142 | document.getElementById("metaperformance").innerHTML = |
| 143 | "completed in " + (end2 - start2) + " milliseconds."; |
| 144 | } |
| 145 | |
| 146 | return millisecondss; |
| 147 | }; |
| 148 | |
| 149 | setDataType = function(radiobutton) { |
| 150 | dataType = radiobutton.value; |
| 151 | }; |
| 152 | setTimestampType = function(radiobutton) { |
| 153 | timestamps = radiobutton.value; |
| 154 | }; |
| 155 | |
| 156 | var values = { |
| 157 | points: 100, |
| 158 | series: 1, |
| 159 | rollPeriod: 1, |
| 160 | repetitions: 1, |
| 161 | type: 'sine' |
| 162 | }; |
| 163 | |
| 164 | // Parse the URL for parameters. Use it to override the values hash. |
| 165 | var href = window.location.href; |
| 166 | var qmindex = href.indexOf('?'); |
| 167 | if (qmindex > 0) { |
| 168 | var entries = href.substr(qmindex + 1).split('&'); |
| 169 | for (var idx = 0; idx < entries.length; idx++) { |
| 170 | var entry = entries[idx]; |
| 171 | var eindex = entry.indexOf('='); |
| 172 | if (eindex > 0) { |
| 173 | values[entry.substr(0, eindex)] = entry.substr(eindex + 1); |
| 174 | } |
| 175 | } |
| 176 | } |
| 177 | |
| 178 | var populate = function(name) { |
| 179 | document.getElementById(name).value = values[name]; |
| 180 | } |
| 181 | |
| 182 | var populateRadio = function(name) { |
| 183 | var val = values[name]; |
| 184 | var elem = document.getElementById(val); |
| 185 | elem.checked = true; |
| 186 | elem.onclick(); |
| 187 | } |
| 188 | |
| 189 | populate('points'); |
| 190 | populate('series'); |
| 191 | populate('rollPeriod'); |
| 192 | populate('repetitions'); |
| 193 | populateRadio('type'); |
| 194 | if (values["go"]) { |
| 195 | updatePlot(); |
| 196 | } |
| 197 | </script> |
| 198 | </body> |
| 199 | </html> |