@@ -30,6 +30,56 @@ class RunData {
3030 this . options = options ;
3131 this . runs = runs ;
3232 }
33+
34+ static resultsDataFromSingleRunData ( singleRunData )
35+ {
36+ RunData . #migrateImportedData( singleRunData ) ;
37+
38+ if ( ! singleRunData . data instanceof Array ) {
39+ console . error ( 'Imported singleRunData.data is not an array. Bailing' ) ;
40+ return null ;
41+ }
42+
43+ return new RunData ( singleRunData . version , singleRunData . options , singleRunData . data ) ;
44+ }
45+
46+ static resultsDataFromBenchmarkRunnerData ( benchmarkData )
47+ {
48+ if ( ! benchmarkData instanceof Array ) {
49+ console . log ( 'Imported benchmarkData is not an array. Bailing' ) ;
50+ return null ;
51+ }
52+
53+ const runData = [ ] ;
54+ for ( const run of benchmarkData ) {
55+ RunData . #migrateImportedData( run ) ;
56+ if ( run . data . length !== 1 ) {
57+ console . error ( 'Imported benchmarkData has a "data" array with an unexpected number of items. Bailing' ) ;
58+ return null ;
59+ }
60+
61+ runData . push ( run . data [ 0 ] ) ;
62+ }
63+
64+ // Version and options data should be these same for each run. Use the first run's information.
65+ return new RunData ( benchmarkData [ 0 ] . version , benchmarkData [ 0 ] . options , runData ) ;
66+ }
67+
68+ static #migrateImportedData( options )
69+ {
70+ if ( ! ( "version" in options ) )
71+ options . version = "1.0" ;
72+
73+ if ( ! ( "frame-rate" in options ) ) {
74+ options . options [ "frame-rate" ] = 60 ;
75+ console . log ( "No frame-rate data; assuming 60fps" )
76+ }
77+
78+ if ( ! ( "system-frame-rate" in options ) ) {
79+ options . options [ "system-frame-rate" ] = 60 ;
80+ console . log ( "No system-frame-rate data; assuming 60fps" )
81+ }
82+ }
3383}
3484
3585class ScoreCalculator {
@@ -109,36 +159,37 @@ class ScoreCalculator {
109159
110160 calculateScore ( data )
111161 {
112- var result = { } ;
162+ const result = { } ;
113163 data [ Strings . json . result ] = result ;
114- var samples = data [ Strings . json . samples ] ;
164+ const samples = data [ Strings . json . samples ] ;
115165 const desiredFrameLength = 1000 / this . _targetFrameRate ;
166+ const complexityKey = Strings . json . complexity ;
116167
117168 function findRegression ( series , profile ) {
118- var minIndex = Math . round ( .025 * series . length ) ;
119- var maxIndex = Math . round ( .975 * ( series . length - 1 ) ) ;
120- var minComplexity = series . getFieldInDatum ( minIndex , Strings . json . complexity ) ;
121- var maxComplexity = series . getFieldInDatum ( maxIndex , Strings . json . complexity ) ;
169+ const minIndex = Math . round ( .025 * series . length ) ;
170+ const maxIndex = Math . round ( .975 * ( series . length - 1 ) ) ;
171+ const minComplexity = series . getFieldInDatum ( minIndex , complexityKey ) ;
172+ const maxComplexity = series . getFieldInDatum ( maxIndex , complexityKey ) ;
122173
123174 if ( Math . abs ( maxComplexity - minComplexity ) < 20 && maxIndex - minIndex < 20 ) {
124175 minIndex = 0 ;
125176 maxIndex = series . length - 1 ;
126- minComplexity = series . getFieldInDatum ( minIndex , Strings . json . complexity ) ;
127- maxComplexity = series . getFieldInDatum ( maxIndex , Strings . json . complexity ) ;
177+ minComplexity = series . getFieldInDatum ( minIndex , complexityKey ) ;
178+ maxComplexity = series . getFieldInDatum ( maxIndex , complexityKey ) ;
128179 }
129180
130- var frameTypeIndex = series . fieldMap [ Strings . json . frameType ] ;
131- var complexityIndex = series . fieldMap [ Strings . json . complexity ] ;
132- var frameLengthIndex = series . fieldMap [ Strings . json . frameLength ] ;
133- var regressionOptions = { desiredFrameLength : desiredFrameLength } ;
181+ const frameTypeIndex = series . fieldMap [ Strings . json . frameType ] ;
182+ const complexityIndex = series . fieldMap [ complexityKey ] ;
183+ const frameLengthIndex = series . fieldMap [ Strings . json . frameLength ] ;
184+ const regressionOptions = { desiredFrameLength : desiredFrameLength } ;
134185 if ( profile )
135186 regressionOptions . preferredProfile = profile ;
136187
137- var regressionSamples = series . slice ( minIndex , maxIndex + 1 ) ;
138- var animationSamples = regressionSamples . data . filter ( ( sample ) => sample [ frameTypeIndex ] == Strings . json . animationFrameType ) ;
139- var regressionData = animationSamples . map ( ( sample ) => [ sample [ complexityIndex ] , sample [ frameLengthIndex ] ] ) ;
188+ const regressionSamples = series . slice ( minIndex , maxIndex + 1 ) ;
189+ const animationSamples = regressionSamples . data . filter ( ( sample ) => sample [ frameTypeIndex ] == Strings . json . animationFrameType ) ;
190+ const regressionData = animationSamples . map ( ( sample ) => [ sample [ complexityIndex ] , sample [ frameLengthIndex ] ] ) ;
140191
141- var regression = new Regression ( regressionData , minIndex , maxIndex , regressionOptions ) ;
192+ const regression = new Regression ( regressionData , minIndex , maxIndex , regressionOptions ) ;
142193 return {
143194 minComplexity : minComplexity ,
144195 maxComplexity : maxComplexity ,
@@ -148,14 +199,14 @@ class ScoreCalculator {
148199 }
149200
150201 // Convert these samples into SampleData objects if needed
151- [ Strings . json . complexity , Strings . json . controller ] . forEach ( function ( seriesName ) {
152- var series = samples [ seriesName ] ;
202+ [ complexityKey , Strings . json . controller ] . forEach ( function ( seriesName ) {
203+ const series = samples [ seriesName ] ;
153204 if ( series && ! ( series instanceof SampleData ) )
154205 samples [ seriesName ] = new SampleData ( series . fieldMap , series . data ) ;
155206 } ) ;
156207
157- var isRampController = this . _runData . options [ Strings . json . controller ] == "ramp" ;
158- var predominantProfile = "" ;
208+ const isRampController = this . _runData . options [ Strings . json . controller ] == "ramp" ;
209+ let predominantProfile = "" ;
159210 if ( isRampController ) {
160211 var profiles = { } ;
161212 data [ Strings . json . controller ] . forEach ( function ( regression ) {
@@ -174,44 +225,44 @@ class ScoreCalculator {
174225 }
175226 }
176227
177- var regressionResult = findRegression ( samples [ Strings . json . complexity ] , predominantProfile ) ;
178- var calculation = regressionResult . regression ;
179- result [ Strings . json . complexity ] = { } ;
180- result [ Strings . json . complexity ] [ Strings . json . regressions . segment1 ] = [
228+ const regressionResult = findRegression ( samples [ complexityKey ] , predominantProfile ) ;
229+ const calculation = regressionResult . regression ;
230+ result [ complexityKey ] = { } ;
231+ result [ complexityKey ] [ Strings . json . regressions . segment1 ] = [
181232 [ regressionResult . minComplexity , calculation . s1 + calculation . t1 * regressionResult . minComplexity ] ,
182233 [ calculation . complexity , calculation . s1 + calculation . t1 * calculation . complexity ]
183234 ] ;
184- result [ Strings . json . complexity ] [ Strings . json . regressions . segment2 ] = [
235+ result [ complexityKey ] [ Strings . json . regressions . segment2 ] = [
185236 [ calculation . complexity , calculation . s2 + calculation . t2 * calculation . complexity ] ,
186237 [ regressionResult . maxComplexity , calculation . s2 + calculation . t2 * regressionResult . maxComplexity ]
187238 ] ;
188- result [ Strings . json . complexity ] [ Strings . json . complexity ] = calculation . complexity ;
189- result [ Strings . json . complexity ] [ Strings . json . measurements . stdev ] = Math . sqrt ( calculation . error / samples [ Strings . json . complexity ] . length ) ;
239+ result [ complexityKey ] [ complexityKey ] = calculation . complexity ;
240+ result [ complexityKey ] [ Strings . json . measurements . stdev ] = Math . sqrt ( calculation . error / samples [ complexityKey ] . length ) ;
190241
191242 result [ Strings . json . fps ] = data . targetFPS ;
192243
193244 if ( isRampController ) {
194- var timeComplexity = new Experiment ;
245+ const timeComplexity = new Experiment ;
195246 data [ Strings . json . controller ] . forEach ( function ( regression ) {
196- timeComplexity . sample ( regression [ Strings . json . complexity ] ) ;
247+ timeComplexity . sample ( regression [ complexityKey ] ) ;
197248 } ) ;
198249
199- var experimentResult = { } ;
250+ const experimentResult = { } ;
200251 result [ Strings . json . controller ] = experimentResult ;
201252 experimentResult [ Strings . json . score ] = timeComplexity . mean ( ) ;
202253 experimentResult [ Strings . json . measurements . average ] = timeComplexity . mean ( ) ;
203254 experimentResult [ Strings . json . measurements . stdev ] = timeComplexity . standardDeviation ( ) ;
204255 experimentResult [ Strings . json . measurements . percent ] = timeComplexity . percentage ( ) ;
205256
206257 const bootstrapIterations = this . _runData . options [ Strings . json . bootstrapIterations ] ;
207- var bootstrapResult = Regression . bootstrap ( regressionResult . samples . data , bootstrapIterations , function ( resampleData ) {
208- var complexityIndex = regressionResult . samples . fieldMap [ Strings . json . complexity ] ;
258+ const bootstrapResult = Regression . bootstrap ( regressionResult . samples . data , bootstrapIterations , function ( resampleData ) {
259+ const complexityIndex = regressionResult . samples . fieldMap [ complexityKey ] ;
209260 resampleData . sort ( function ( a , b ) {
210261 return a [ complexityIndex ] - b [ complexityIndex ] ;
211262 } ) ;
212263
213- var resample = new SampleData ( regressionResult . samples . fieldMap , resampleData ) ;
214- var bootstrapRegressionResult = findRegression ( resample , predominantProfile ) ;
264+ const resample = new SampleData ( regressionResult . samples . fieldMap , resampleData ) ;
265+ const bootstrapRegressionResult = findRegression ( resample , predominantProfile ) ;
215266 if ( bootstrapRegressionResult . regression . t2 < 0 ) {
216267 // A positive slope means the frame rate decreased with increased complexity (which is the expected
217268 // benavior). OTOH, a negative slope means the framerate increased as the complexity increased. This
@@ -224,24 +275,24 @@ class ScoreCalculator {
224275 return bootstrapRegressionResult . regression . complexity ;
225276 } , .8 ) ;
226277
227- result [ Strings . json . complexity ] [ Strings . json . bootstrap ] = bootstrapResult ;
278+ result [ complexityKey ] [ Strings . json . bootstrap ] = bootstrapResult ;
228279 result [ Strings . json . score ] = bootstrapResult . median ;
229280 result [ Strings . json . scoreLowerBound ] = bootstrapResult . confidenceLow ;
230281 result [ Strings . json . scoreUpperBound ] = bootstrapResult . confidenceHigh ;
231282 } else {
232- var marks = data [ Strings . json . marks ] ;
233- var samplingStartIndex = 0 , samplingEndIndex = - 1 ;
283+ const marks = data [ Strings . json . marks ] ;
284+ let samplingStartIndex = 0 , samplingEndIndex = - 1 ;
234285 if ( Strings . json . samplingStartTimeOffset in marks )
235286 samplingStartIndex = marks [ Strings . json . samplingStartTimeOffset ] . index ;
236287 if ( Strings . json . samplingEndTimeOffset in marks )
237288 samplingEndIndex = marks [ Strings . json . samplingEndTimeOffset ] . index ;
238289
239- var averageComplexity = new Experiment ;
240- var averageFrameLength = new Experiment ;
241- var controllerSamples = samples [ Strings . json . controller ] ;
290+ const averageComplexity = new Experiment ;
291+ const averageFrameLength = new Experiment ;
292+ const controllerSamples = samples [ Strings . json . controller ] ;
242293 controllerSamples . forEach ( function ( sample , i ) {
243294 if ( i >= samplingStartIndex && ( samplingEndIndex == - 1 || i < samplingEndIndex ) ) {
244- averageComplexity . sample ( controllerSamples . getFieldInDatum ( sample , Strings . json . complexity ) ) ;
295+ averageComplexity . sample ( controllerSamples . getFieldInDatum ( sample , complexityKey ) ) ;
245296 var smoothedFrameLength = controllerSamples . getFieldInDatum ( sample , Strings . json . smoothedFrameLength ) ;
246297 if ( smoothedFrameLength && smoothedFrameLength != - 1 )
247298 averageFrameLength . sample ( smoothedFrameLength ) ;
@@ -346,14 +397,14 @@ class ResultsTable {
346397
347398 _addHeader ( )
348399 {
349- var thead = Utilities . createElement ( "thead" , { } , this . element ) ;
350- var row = Utilities . createElement ( "tr" , { } , thead ) ;
400+ const thead = Utilities . createElement ( "thead" , { } , this . element ) ;
401+ const row = Utilities . createElement ( "tr" , { } , thead ) ;
351402
352403 this . _headers . forEach ( function ( header ) {
353404 if ( header . disabled )
354405 return ;
355406
356- var th = Utilities . createElement ( "th" , { } , row ) ;
407+ const th = Utilities . createElement ( "th" , { } , row ) ;
357408 if ( header . title != Strings . text . graph )
358409 th . innerHTML = header . title ;
359410 if ( header . children )
@@ -368,18 +419,18 @@ class ResultsTable {
368419
369420 _addEmptyRow ( )
370421 {
371- var row = Utilities . createElement ( "tr" , { } , this . tbody ) ;
422+ const row = Utilities . createElement ( "tr" , { } , this . tbody ) ;
372423 this . _flattenedHeaders . forEach ( function ( header ) {
373424 return Utilities . createElement ( "td" , { class : "suites-separator" } , row ) ;
374425 } ) ;
375426 }
376427
377428 _addTest ( testName , testResult , options )
378429 {
379- var row = Utilities . createElement ( "tr" , { } , this . tbody ) ;
430+ const row = Utilities . createElement ( "tr" , { } , this . tbody ) ;
380431
381432 this . _flattenedHeaders . forEach ( function ( header ) {
382- var td = Utilities . createElement ( "td" , { } , row ) ;
433+ const td = Utilities . createElement ( "td" , { } , row ) ;
383434 if ( header . text == Strings . text . testName ) {
384435 td . textContent = testName ;
385436 } else if ( typeof header . text == "string" ) {
@@ -394,12 +445,12 @@ class ResultsTable {
394445
395446 _addIteration ( iterationResult , iterationData , options )
396447 {
397- var testsResults = iterationResult [ Strings . json . results . tests ] ;
398- for ( var suiteName in testsResults ) {
448+ const testsResults = iterationResult [ Strings . json . results . tests ] ;
449+ for ( const suiteName in testsResults ) {
399450 this . _addEmptyRow ( ) ;
400- var suiteResult = testsResults [ suiteName ] ;
401- var suiteData = iterationData [ suiteName ] ;
402- for ( var testName in suiteResult )
451+ const suiteResult = testsResults [ suiteName ] ;
452+ const suiteData = iterationData [ suiteName ] ;
453+ for ( let testName in suiteResult )
403454 this . _addTest ( testName , suiteResult [ testName ] , options , suiteData [ testName ] ) ;
404455 }
405456 }
@@ -410,7 +461,7 @@ class ResultsTable {
410461 this . _addHeader ( ) ;
411462 this . _addBody ( ) ;
412463
413- var iterationsResults = scoreCalculator . results ;
464+ const iterationsResults = scoreCalculator . results ;
414465 iterationsResults . forEach ( function ( iterationResult , index ) {
415466 this . _addIteration ( iterationResult , scoreCalculator . data [ index ] , scoreCalculator . options ) ;
416467 } , this ) ;
0 commit comments