| OLD | NEW |
| 1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
| 2 <!-- | 2 <!-- |
| 3 Copyright (c) 2014 The Chromium Authors. All rights reserved. | 3 Copyright (c) 2014 The Chromium Authors. All rights reserved. |
| 4 Use of this source code is governed by a BSD-style license that can be | 4 Use of this source code is governed by a BSD-style license that can be |
| 5 found in the LICENSE file. | 5 found in the LICENSE file. |
| 6 --> | 6 --> |
| 7 | 7 |
| 8 <link rel="import" href="/tracing/base/math.html"> | 8 <link rel="import" href="/tracing/base/math.html"> |
| 9 <link rel="import" href="/tracing/base/range.html"> | 9 <link rel="import" href="/tracing/base/range.html"> |
| 10 <script src="/mannwhitneyu/mannwhitneyu.js"></script> |
| 10 | 11 |
| 11 <script> | 12 <script> |
| 12 'use strict'; | 13 'use strict'; |
| 14 // In node, the script-src for mannwhitneyu above brings in mannwhitneyui |
| 15 // into a module, instead of into the global scope. Whereas this file |
| 16 // assumes that mannwhitneyu is in the global scope. So, in Node only, we |
| 17 // require() it in, and then take all its exports and shove them into the |
| 18 // global scope by hand. |
| 19 (function(global) { |
| 20 if (tr.isNode) { |
| 21 var mwuAbsPath = HTMLImportsLoader.hrefToAbsolutePath( |
| 22 '/mannwhitneyu.js'); |
| 23 var mwuModule = require(mwuAbsPath); |
| 24 for (var exportName in mwuModule) { |
| 25 global[exportName] = mwuModule[exportName]; |
| 26 } |
| 27 } |
| 28 })(this); |
| 29 </script> |
| 30 |
| 31 <script> |
| 32 'use strict'; |
| 13 | 33 |
| 14 tr.exportTo('tr.b', function() { | 34 tr.exportTo('tr.b', function() { |
| 15 | 35 |
| 16 function identity(d) { | 36 function identity(d) { |
| 17 return d; | 37 return d; |
| 18 } | 38 } |
| 19 | 39 |
| 20 function Statistics() { | 40 function Statistics() { |
| 21 } | 41 } |
| 22 | 42 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 var func = opt_func || identity; | 144 var func = opt_func || identity; |
| 125 var tmp = new Array(ary.length); | 145 var tmp = new Array(ary.length); |
| 126 var i = 0; | 146 var i = 0; |
| 127 for (var elt of ary) | 147 for (var elt of ary) |
| 128 tmp[i] = func.call(opt_this, elt, i++); | 148 tmp[i] = func.call(opt_this, elt, i++); |
| 129 tmp.sort((a, b) => a - b); | 149 tmp.sort((a, b) => a - b); |
| 130 var idx = Math.floor((ary.length - 1) * percent); | 150 var idx = Math.floor((ary.length - 1) * percent); |
| 131 return tmp[idx]; | 151 return tmp[idx]; |
| 132 }; | 152 }; |
| 133 | 153 |
| 134 /* Clamp a value between some low and high value. */ | |
| 135 Statistics.clamp = function(value, opt_low, opt_high) { | |
| 136 opt_low = opt_low || 0.0; | |
| 137 opt_high = opt_high || 1.0; | |
| 138 return Math.min(Math.max(value, opt_low), opt_high); | |
| 139 }; | |
| 140 | |
| 141 /** | 154 /** |
| 142 * Sorts the samples, and map them linearly to the range [0,1]. | 155 * Sorts the samples, and map them linearly to the range [0,1]. |
| 143 * | 156 * |
| 144 * They're mapped such that for the N samples, the first sample is 0.5/N and | 157 * They're mapped such that for the N samples, the first sample is 0.5/N and |
| 145 * the last sample is (N-0.5)/N. | 158 * the last sample is (N-0.5)/N. |
| 146 * | 159 * |
| 147 * Background: The discrepancy of the sample set i/(N-1); i=0, ..., N-1 is | 160 * Background: The discrepancy of the sample set i/(N-1); i=0, ..., N-1 is |
| 148 * 2/N, twice the discrepancy of the sample set (i+1/2)/N; i=0, ..., N-1. In | 161 * 2/N, twice the discrepancy of the sample set (i+1/2)/N; i=0, ..., N-1. In |
| 149 * our case we don't want to distinguish between these two cases, as our | 162 * our case we don't want to distinguish between these two cases, as our |
| 150 * original domain is not bounded (it is for Monte Carlo integration, where | 163 * original domain is not bounded (it is for Monte Carlo integration, where |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 var s = Statistics.normalizeSamples(timestamps); | 348 var s = Statistics.normalizeSamples(timestamps); |
| 336 var samples = s.normalized_samples; | 349 var samples = s.normalized_samples; |
| 337 var sample_scale = s.scale; | 350 var sample_scale = s.scale; |
| 338 var discrepancy = Statistics.discrepancy(samples, opt_location_count); | 351 var discrepancy = Statistics.discrepancy(samples, opt_location_count); |
| 339 var inv_sample_count = 1.0 / samples.length; | 352 var inv_sample_count = 1.0 / samples.length; |
| 340 if (opt_absolute === true) { | 353 if (opt_absolute === true) { |
| 341 // Compute absolute discrepancy | 354 // Compute absolute discrepancy |
| 342 discrepancy /= sample_scale; | 355 discrepancy /= sample_scale; |
| 343 } else { | 356 } else { |
| 344 // Compute relative discrepancy | 357 // Compute relative discrepancy |
| 345 discrepancy = Statistics.clamp( | 358 discrepancy = tr.b.clamp( |
| 346 (discrepancy - inv_sample_count) / (1.0 - inv_sample_count)); | 359 (discrepancy - inv_sample_count) / (1.0 - inv_sample_count), 0.0, 1.0); |
| 347 } | 360 } |
| 348 return discrepancy; | 361 return discrepancy; |
| 349 }; | 362 }; |
| 350 | 363 |
| 351 /** | 364 /** |
| 352 * A discrepancy based metric for measuring duration jank. | 365 * A discrepancy based metric for measuring duration jank. |
| 353 * | 366 * |
| 354 * DurationsDiscrepancy computes a jank metric which measures how irregular a | 367 * DurationsDiscrepancy computes a jank metric which measures how irregular a |
| 355 * given sequence of intervals is. In order to minimize jank, each duration | 368 * given sequence of intervals is. In order to minimize jank, each duration |
| 356 * should be equally long. This is similar to how timestamp jank works, | 369 * should be equally long. This is similar to how timestamp jank works, |
| (...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 732 */ | 745 */ |
| 733 Statistics.LogNormalDistribution.fromMedianAndDiminishingReturns = | 746 Statistics.LogNormalDistribution.fromMedianAndDiminishingReturns = |
| 734 function(median, diminishingReturns) { | 747 function(median, diminishingReturns) { |
| 735 diminishingReturns = Math.log(diminishingReturns / median); | 748 diminishingReturns = Math.log(diminishingReturns / median); |
| 736 var shape = Math.sqrt(1 - 3 * diminishingReturns - | 749 var shape = Math.sqrt(1 - 3 * diminishingReturns - |
| 737 Math.sqrt(Math.pow(diminishingReturns - 3, 2) - 8)) / 2; | 750 Math.sqrt(Math.pow(diminishingReturns - 3, 2) - 8)) / 2; |
| 738 var location = Math.log(median); | 751 var location = Math.log(median); |
| 739 return new Statistics.LogNormalDistribution(location, shape); | 752 return new Statistics.LogNormalDistribution(location, shape); |
| 740 }; | 753 }; |
| 741 | 754 |
| 755 Statistics.mwu = mannwhitneyu; |
| 756 |
| 742 return { | 757 return { |
| 743 Statistics: Statistics | 758 Statistics: Statistics |
| 744 }; | 759 }; |
| 745 }); | 760 }); |
| 746 </script> | 761 </script> |
| OLD | NEW |