• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!DOCTYPE HTML>
2<html>
3    <head>
4        <title>Performance Tests (2)</title>
5        <style>
6            body { font-family: Tahoma, Serif; font-size: 9pt; }
7
8            .left { text-align: left; }
9            .right { text-align: right; }
10            .center { text-align: center; }
11
12            table.resultTable
13            {
14                border: 1px solid black;
15                border-collapse: collapse;
16                empty-cells: show;
17                width: 100%;
18            }
19            table.resultTable td
20            {
21                padding: 2px 4px;
22                border: 1px solid black;
23            }
24            table.resultTable > thead > tr
25            {
26                font-weight: bold;
27                background: lightblue;
28            }
29            table.resultTable > tbody > tr:nth-child(odd)
30            {
31                background: white;
32            }
33            table.resultTable > tbody > tr:nth-child(even)
34            {
35                background: lightgray;
36            }
37
38            .hide { display: none; }
39        </style>
40    </head>
41    <body bgcolor="white">
42        <h1>Performance Tests (2)</h1>
43
44        <form id="sForm" onsubmit="runTestSuite();return false">
45            <table>
46                <tr>
47                    <td colspan="2">Settings:</td>
48                </tr>
49                <tr>
50                    <td class="right">Iterations:</td>
51                    <td><input id="sIterations" type="text" value="1000" required pattern="[0-9]+" /></td>
52                </tr>
53                <tr>
54                    <td class="right">Samples:</td>
55                    <td><input id="sSamples" type="text" value="100" required pattern="[0-9]+" /></td>
56                </tr>
57                <tr>
58                    <td class="right">Mode:</td>
59                    <td><input id="sAsync" name="sMode" type="radio" value="async" checked>Asynchronous</input>
60                        <input id="sSync" name="sMode" type="radio" value="sync">Synchronous</input>
61                    </td>
62                </tr>
63                <tr>
64                    <td colspan="2"><button type="submit" id="sRun" autofocus>Run!</button></td>
65                </tr>
66            </table>
67        </form>
68
69
70        <div><span id="statusBox"></span> <progress id="progressBox" value="0" style="display:none"></progress></div>
71
72        <div style="padding-top:10px; padding-bottom:10px">
73        <table id="resultTable" class="resultTable">
74            <thead>
75                <tr>
76                    <td class="center" style="width:1%">Enabled</td>
77                    <td class="center" style="width:10%">Name</td>
78                    <td class="center" style="width:5%">Samples x Iterations</td>
79                    <td class="center" style="width:5%">Min,&nbsp;ms</td>
80                    <td class="center" style="width:5%">Avg,&nbsp;ms</td>
81                    <td class="center" style="width:5%">Max,&nbsp;ms</td>
82                    <td class="center" style="width:5%">Average calls/sec</td>
83                    <td class="center" style="width:5%">Measuring Inacurracy</td>
84                    <td class="center hide" style="width:5%">Memory, MB</td>
85                    <td class="center hide" style="width:5%">Memory delta, MB</td>
86                    <td class="center" style="width:55%">Description</td>
87                </tr>
88            </thead>
89            <tbody>
90                <!-- result rows here -->
91            </tbody>
92        </table>
93        </div>
94
95<script type="text/javascript">
96(function () {
97    function getPrivateWorkingSet() {
98        return 0; // TODO: window.PerfTestGetPrivateWorkingSet();
99    }
100
101    var disableWarmUp = true;
102
103    var asyncExecution = true;
104    var testIterations = 1000;
105    var totalSamples = 100;
106    var sampleDelay = 0;
107
108    var collectSamples = false;
109
110    var tests = [];
111    var testIndex = -1;
112
113    function execTestFunc(test) {
114        try {
115            var begin = new Date();
116            test.func(test.totalIterations);
117            var end = new Date();
118            return (end - begin);
119        } catch (e) {
120            test.error = e.toString();
121            return 0;
122        }
123    }
124
125    function execTest(test) {
126        if (disableWarmUp) { test.warmedUp = true; }
127
128        function nextStep() {
129            if (asyncExecution) {
130                setTimeout(function () { execTest(test); }, sampleDelay);
131            } else {
132                execTest(test);
133            }
134        }
135
136        function nextTest() {
137            updateStatus(test);
138            appendResult(test);
139
140            return execNextTest();
141        }
142
143        updateStatus(test);
144        if (!test.warmedUp) {
145            execTestFunc(test);
146            if (!test.error) {
147                test.warmedUp = true;
148                test.beginMemory = getPrivateWorkingSet();
149                return nextStep();
150            } else {
151                return nextTest();
152            }
153        }
154
155        if (test.sample >= test.totalSamples) {
156            test.avg = test.total / test.totalSamples;
157            test.endMemory = getPrivateWorkingSet();
158            return nextTest();
159        }
160
161        if (test.skipped) return nextTest();
162
163        var elapsed = execTestFunc(test);
164        if (!test.error) {
165            test.total += elapsed;
166            if (!test.min) test.min = elapsed;
167            else if (test.min > elapsed) test.min = elapsed;
168            if (!test.max) test.max = elapsed;
169            else if (test.max < elapsed) test.max = elapsed;
170            if (collectSamples) {
171                test.results.push(elapsed);
172            }
173            test.sample++;
174            return nextStep();
175        } else {
176            return nextTest();
177        }
178    }
179
180    function updateStatus(test) {
181        var statusBox = document.getElementById("statusBox");
182        var progressBox = document.getElementById("progressBox");
183
184        if (test.skipped || test.error || test.sample >= test.totalSamples) {
185            statusBox.innerText = "";
186            progressBox.style.display = "none";
187        } else {
188            statusBox.innerText = (testIndex + 1) + "/" + tests.length + ": " + test.name + " (" + test.sample + "/" + test.totalSamples + ")";
189            progressBox.value = (test.sample / test.totalSamples);
190            progressBox.style.display = "inline";
191        }
192    }
193
194    function appendResult(test) {
195        if (test.name == "warmup") return;
196
197        var id = "testResultRow_" + test.index;
198
199        var nearBound = (test.max - test.avg) < (test.avg - test.min) ? test.max : test.min;
200        var memoryDelta = test.endMemory - test.beginMemory;
201        if (memoryDelta < 0) memoryDelta = "-" + Math.abs(memoryDelta).toFixed(2);
202        else memoryDelta = "+" + Math.abs(memoryDelta).toFixed(2);
203
204        var markup = ["<tr id='" + id + "'>",
205                      "<td class='left'><input type='checkbox' id='test_enabled_", test.index ,"' ", (!test.skipped ? "checked" : "") ," /></td>",
206                      "<td class='left'>", test.name, "</td>",
207                      "<td class='right'>", test.totalSamples, "x", test.totalIterations, "</td>",
208                      "<td class='right'>", test.skipped || test.error || !test.prepared ? "-" : test.min.toFixed(2), "</td>",
209                      "<td class='right'>", test.skipped || test.error || !test.prepared ? "-" : test.avg.toFixed(2), "</td>",
210                      "<td class='right'>", test.skipped || test.error || !test.prepared ? "-" : test.max.toFixed(2), "</td>",
211                      "<td class='right'>", test.skipped || test.error || !test.prepared ? "-" : (test.totalIterations * 1000 / test.avg).toFixed(2), "</td>",
212                      "<td class='right'>", test.skipped || test.error || !test.prepared ? "-" : ("&#x00B1; " + (Math.abs(test.avg - nearBound) / (test.avg) * (100)).toFixed(2) + "%"), "</td>",
213                      "<td class='right hide'>", test.skipped || test.error || !test.prepared ? "-" : test.endMemory.toFixed(2), "</td>",
214                      "<td class='right hide'>", test.skipped || test.error || !test.prepared ? "-" : memoryDelta, "</td>",
215                      "<td class='left'>", test.description, test.error ? (test.description ? "<br/>" : "") + "<span style='color:red'>" + test.error + "</span>" : "", "</td>",
216                      "</tr>"
217                      ].join("");
218        // test.results.join(", "), "<br/>",
219
220        var row = document.getElementById(id);
221        if (row) {
222            row.outerHTML = markup;
223        } else {
224            var tbody = document.getElementById("resultTable").tBodies[0];
225            tbody.insertAdjacentHTML("beforeEnd", markup);
226        }
227    }
228
229    function prepareQueuedTests() {
230        testIndex = -1;
231        for (var i = 0; i < tests.length; i++) {
232            var test = tests[i];
233            test.index = i;
234            test.prepared = false;
235            test.warmedUp = false;
236            test.sample = 0;
237            test.total = 0;
238            test.results = [];
239            test.error = false;
240            test.min = null;
241            test.avg = null;
242            test.max = null;
243            test.beginMemory = null;
244            test.endMemory = null;
245            test.totalIterations = parseInt(testIterations / test.complex);
246            test.totalSamples = parseInt(totalSamples / test.complex);
247
248            var skipElement = document.getElementById('test_enabled_' + test.index);
249            test.skipped = skipElement ? !skipElement.checked : (test.skipped || false);
250
251            if (test.totalIterations <= 0) test.totalIterations = 1;
252            if (test.totalSamples <= 0) test.totalSamples = 1;
253
254            appendResult(test);
255            test.prepared = true;
256        }
257    }
258
259    function queueTest(func, name, description) {
260        var test;
261        if (typeof func === "function") {
262            test = {
263                name: name,
264                func: func,
265                description: description
266            };
267        } else {
268            test = func;
269        }
270        test.warmedUp = false;
271        test.complex = test.complex || 1;
272        tests.push(test);
273    }
274
275    function execNextTest() {
276        testIndex++;
277        if (tests.length <= testIndex) {
278            return testSuiteFinished();
279        } else {
280            return execTest(tests[testIndex]);
281        }
282    }
283
284    function execQueuedTests() {
285        prepareQueuedTests();
286        execNextTest();
287    }
288
289    function setSettingsState(disabled) {
290        document.getElementById('sIterations').disabled = disabled;
291        document.getElementById('sSamples').disabled = disabled;
292        document.getElementById('sAsync').disabled = disabled;
293        document.getElementById('sSync').disabled = disabled;
294        document.getElementById('sRun').disabled = disabled;
295    }
296
297    function testSuiteFinished() {
298        setSettingsState(false);
299    }
300
301    window.runTestSuite = function () {
302        setSettingsState(true);
303
304        testIterations = parseInt(document.getElementById('sIterations').value);
305        totalSamples = parseInt(document.getElementById('sSamples').value);
306        asyncExecution = document.getElementById('sAsync').checked;
307
308        setTimeout(execQueuedTests, 0);
309    }
310
311    setTimeout(prepareQueuedTests, 0);
312
313    // Test queue.
314    queueTest({
315        name: "PerfTestReturnValue Default",
316        func: function (count) {
317            for (var i = 0; i < count; i++) {
318                window.PerfTestReturnValue();
319            }
320        },
321        description: "No arguments, returns int32 value.",
322        skipped: true,
323    });
324
325    queueTest({
326        name: "PerfTestReturnValue (0, Undefined)",
327        func: function (count) {
328            for (var i = 0; i < count; i++) {
329                window.PerfTestReturnValue(0);
330            }
331        },
332        description: "Int argument, returns undefined value."
333    });
334
335    queueTest({
336        name: "PerfTestReturnValue (1, Null)",
337        func: function (count) {
338            for (var i = 0; i < count; i++) {
339                window.PerfTestReturnValue(1);
340            }
341        },
342        description: "Int argument, returns null value."
343    });
344
345    queueTest({
346        name: "PerfTestReturnValue (2, Bool)",
347        func: function (count) {
348            for (var i = 0; i < count; i++) {
349                window.PerfTestReturnValue(2);
350            }
351        },
352        description: "Int argument, returns bool value."
353    });
354
355    queueTest({
356        name: "PerfTestReturnValue (3, Int)",
357        func: function (count) {
358            for (var i = 0; i < count; i++) {
359                window.PerfTestReturnValue(3);
360            }
361        },
362        description: "Int argument, returns int value."
363    });
364
365    queueTest({
366        name: "PerfTestReturnValue (4, UInt)",
367        func: function (count) {
368            for (var i = 0; i < count; i++) {
369                window.PerfTestReturnValue(4);
370            }
371        },
372        description: "Int argument, returns uint value."
373    });
374
375    queueTest({
376        name: "PerfTestReturnValue (5, Double)",
377        func: function (count) {
378            for (var i = 0; i < count; i++) {
379                window.PerfTestReturnValue(5);
380            }
381        },
382        description: "Int argument, returns double value."
383    });
384
385    queueTest({
386        name: "PerfTestReturnValue (6, Date)",
387        func: function (count) {
388            for (var i = 0; i < count; i++) {
389                window.PerfTestReturnValue(6);
390            }
391        },
392        description: "Int argument, returns date value.",
393        skipped: true,
394    });
395
396    queueTest({
397        name: "PerfTestReturnValue (7, String)",
398        func: function (count) {
399            for (var i = 0; i < count; i++) {
400                window.PerfTestReturnValue(7);
401            }
402        },
403        description: "Int argument, returns string value."
404    });
405
406    queueTest({
407        name: "PerfTestReturnValue (8, Object)",
408        func: function (count) {
409            for (var i = 0; i < count; i++) {
410                window.PerfTestReturnValue(8);
411            }
412        },
413        description: "Int argument, returns object value."
414    });
415
416    queueTest({
417        name: "PerfTestReturnValue (9, Array)",
418        func: function (count) {
419            for (var i = 0; i < count; i++) {
420                window.PerfTestReturnValue(9);
421            }
422        },
423        description: "Int argument, returns array value."
424    });
425
426    queueTest({
427        name: "PerfTestReturnValue (10, Function)",
428        func: function (count) {
429            for (var i = 0; i < count; i++) {
430                window.PerfTestReturnValue(10);
431            }
432        },
433        description: "Int argument, returns function value.",
434        skipped: true,
435    });
436    // add more tests to queueTest
437
438})();
439</script>
440
441    </body>
442</html>
443