@@ -16,6 +16,10 @@ var COLORS = [
1616] ;
1717function getColor ( i ) { return COLORS [ i % COLORS . length ] ; }
1818
19+ function getExeLabel ( key ) {
20+ return $ ( "label[for='exe_" + key . replace ( / : / g, '\\:' ) + "']" ) . text ( ) . trim ( ) ;
21+ }
22+
1923function getConfiguration ( ) {
2024 return {
2125 exe : readCheckbox ( "input[name='executables']:checked" ) ,
@@ -27,13 +31,94 @@ function getConfiguration() {
2731 } ;
2832}
2933
34+ function updateGraphTitle ( exes , enviros , bens , baseline , chart , chartTitles ) {
35+ var $title = $ ( "#graph-title" ) ;
36+
37+ if ( enviros . length === 1 && exes . length === 2 && baseline !== "none" &&
38+ chart !== "stacked bars" && compdata ) {
39+
40+ var baselineExe = baseline , baselineEnv = null ;
41+ if ( baseline . indexOf ( '@' ) !== - 1 ) {
42+ var bparts = baseline . split ( '@' ) ;
43+ baselineExe = bparts [ 0 ] ;
44+ baselineEnv = bparts [ 1 ] ;
45+ }
46+
47+ var otherExes = exes . filter ( function ( e ) { return e !== baselineExe ; } ) ;
48+ if ( otherExes . length === 1 ) {
49+ var otherExe = otherExes [ 0 ] ;
50+ var envId = enviros [ 0 ] ;
51+ var envForBase = baselineEnv !== null ? baselineEnv : envId ;
52+
53+ var product = 1 , count = 0 ;
54+ for ( var b = 0 ; b < bens . length ; b ++ ) {
55+ var val = compdata [ otherExe ] && compdata [ otherExe ] [ envId ]
56+ ? compdata [ otherExe ] [ envId ] [ bens [ b ] ]
57+ : null ;
58+ var baseval = compdata [ baselineExe ] && compdata [ baselineExe ] [ envForBase ]
59+ ? compdata [ baselineExe ] [ envForBase ] [ bens [ b ] ]
60+ : null ;
61+ if ( val !== null && baseval !== null && baseval !== 0 && val > 0 ) {
62+ product *= val / baseval ;
63+ count ++ ;
64+ }
65+ }
66+
67+ if ( count > 0 ) {
68+ var geomean = Math . pow ( product , 1 / count ) ;
69+
70+ var lessCount = 0 , moreCount = 0 ;
71+ var benSet = { } ;
72+ for ( var b = 0 ; b < bens . length ; b ++ ) { benSet [ bens [ b ] ] = true ; }
73+ for ( var u in bench_units ) {
74+ var unitBens = bench_units [ u ] [ 0 ] ;
75+ var unitLess = bench_units [ u ] [ 1 ] . indexOf ( "less" ) !== - 1 ;
76+ for ( var ub = 0 ; ub < unitBens . length ; ub ++ ) {
77+ if ( benSet [ unitBens [ ub ] ] ) {
78+ if ( unitLess ) { lessCount ++ ; } else { moreCount ++ ; }
79+ }
80+ }
81+ }
82+
83+ var otherLabel = getExeLabel ( otherExe ) ;
84+ var baselineLabel = getExeLabel ( baselineExe ) ;
85+ if ( baselineEnv !== null ) {
86+ baselineLabel += ' @ ' + $ ( "label[for='env_" + baselineEnv + "']" ) . text ( ) . trim ( ) ;
87+ }
88+
89+ var suffix ;
90+ if ( moreCount === 0 && lessCount > 0 ) {
91+ suffix = geomean < 1
92+ ? ' or <strong>' + ( 1 / geomean ) . toFixed ( 1 ) + '×</strong> faster'
93+ : ' or <strong>' + geomean . toFixed ( 1 ) + '×</strong> slower' ;
94+ } else if ( lessCount === 0 && moreCount > 0 ) {
95+ suffix = geomean > 1
96+ ? ' or <strong>' + geomean . toFixed ( 1 ) + '×</strong> faster'
97+ : ' or <strong>' + ( 1 / geomean ) . toFixed ( 1 ) + '×</strong> slower' ;
98+ } else {
99+ suffix = ' relative to baseline' ;
100+ }
101+
102+ $title . html ( 'The geometric average of ' + count + ' benchmarks for <strong>' +
103+ otherLabel + '</strong> is <strong>' + geomean . toFixed ( 2 ) + '</strong>' +
104+ suffix + ' than the baseline <strong>' + baselineLabel + '</strong>' ) ;
105+ return ;
106+ }
107+ }
108+ }
109+
110+ // Fall back to the chart title(s)
111+ $title . text ( chartTitles . join ( ' / ' ) ) ;
112+ }
113+
30114function refreshContent ( ) {
31115 var conf = getConfiguration ( ) ,
32116 exes = conf . exe . split ( "," ) ,
33117 bens = conf . ben . split ( "," ) ,
34118 enviros = conf . env . split ( "," ) ,
35119 msg = "" ;
36120
121+ $ ( "#graph-title" ) . html ( "" ) ;
37122 var h = $ ( "#plotwrapper" ) . height ( ) ; //get height for error message
38123 if ( exes [ 0 ] === "" ) {
39124 $ ( "#plotwrapper" ) . html ( '<p class="warning">No executables selected</p>' ) ;
@@ -73,6 +158,7 @@ function refreshContent() {
73158 $ ( "#plotwrapper" ) . fadeOut ( "fast" , function ( ) {
74159 $ ( this ) . html ( msg ) . show ( ) ;
75160 var plotcounter = 1 ;
161+ var chartTitles = [ ] ;
76162 for ( var unit in bench_units ) {
77163 var benchmarks = [ ] ;
78164 for ( var ben in bens ) {
@@ -85,8 +171,9 @@ function refreshContent() {
85171 var plotid = "plot" + plotcounter ;
86172 $ ( "#plotwrapper" ) . append ( '<div class="compplot-wrap"><canvas id="' + plotid + '"></canvas></div>' ) ;
87173 plotcounter ++ ;
88- renderComparisonPlot ( plotid , unit , benchmarks , exes , enviros , conf . bas , conf . chart , conf . hor ) ;
174+ chartTitles . push ( renderComparisonPlot ( plotid , unit , benchmarks , exes , enviros , conf . bas , conf . chart , conf . hor ) ) ;
89175 }
176+ updateGraphTitle ( exes , enviros , bens , conf . bas , conf . chart , chartTitles ) ;
90177 } ) ;
91178}
92179
@@ -114,7 +201,7 @@ function updateBaselineDropdown() {
114201 if ( multiEnv ) {
115202 enviros . forEach ( function ( envId ) {
116203 var envName = $ ( "label[for='env_" + envId + "']" ) . text ( ) . trim ( ) ;
117- $baseline . append ( $ ( '<option>' ) . val ( key + ': ' + envId ) . text ( name + ' @ ' + envName ) ) ;
204+ $baseline . append ( $ ( '<option>' ) . val ( key + '@ ' + envId ) . text ( name + ' @ ' + envName ) ) ;
118205 } ) ;
119206 } else {
120207 $baseline . append ( $ ( '<option>' ) . val ( key ) . text ( name ) ) ;
@@ -144,18 +231,18 @@ function loadData() {
144231}
145232
146233function renderComparisonPlot ( plotid , unit , benchmarks , exes , enviros , baseline , chart , horizontal ) {
147- // baseline may be "exe_key" or "exe_key: env_id" (for cross-env normalization)
234+ // baseline may be "exe_key" or "exe_key@ env_id" (for cross-env normalization)
148235 if ( ! baseline ) { baseline = "none" ; }
149236 var baselineExe = baseline , baselineEnv = null ;
150- if ( baseline !== "none" && baseline . indexOf ( ': ' ) !== - 1 ) {
151- var bparts = baseline . split ( ': ' ) ;
237+ if ( baseline !== "none" && baseline . indexOf ( '@ ' ) !== - 1 ) {
238+ var bparts = baseline . split ( '@ ' ) ;
152239 baselineExe = bparts [ 0 ] ;
153240 baselineEnv = bparts [ 1 ] ;
154241 }
155242
156243 var baselineLabel = "" ;
157244 if ( baseline !== "none" ) {
158- baselineLabel = $ ( "label[for='exe_" + baselineExe + "']" ) . text ( ) . trim ( ) ;
245+ baselineLabel = getExeLabel ( baselineExe ) ;
159246 if ( baselineEnv !== null ) {
160247 baselineLabel += ' @ ' + $ ( "label[for='env_" + baselineEnv + "']" ) . text ( ) . trim ( ) ;
161248 }
@@ -187,7 +274,7 @@ function renderComparisonPlot(plotid, unit, benchmarks, exes, enviros, baseline,
187274 }
188275 for ( var i = 0 ; i < exes . length ; i ++ ) {
189276 for ( var j = 0 ; j < enviros . length ; j ++ ) {
190- var exeLabel = $ ( "label[for='exe_" + exes [ i ] + "']" ) . text ( ) . trim ( ) ;
277+ var exeLabel = getExeLabel ( exes [ i ] ) ;
191278 if ( chart === "relative bars" && exes [ i ] === baselineExe &&
192279 ( baselineEnv === null || baselineEnv === enviros [ j ] ) ) { continue ; }
193280 var data = [ ] ;
@@ -218,7 +305,7 @@ function renderComparisonPlot(plotid, unit, benchmarks, exes, enviros, baseline,
218305 // Labels = exe@env names
219306 for ( var i = 0 ; i < exes . length ; i ++ ) {
220307 for ( var j = 0 ; j < enviros . length ; j ++ ) {
221- var exeLabel = $ ( "label[for='exe_" + exes [ i ] + "']" ) . text ( ) . trim ( ) ;
308+ var exeLabel = getExeLabel ( exes [ i ] ) ;
222309 labels . push ( exeLabel + ( enviros . length > 1 ? " @ " + $ ( "label[for='env_" + enviros [ j ] + "']" ) . text ( ) . trim ( ) : "" ) ) ;
223310 }
224311 }
@@ -286,7 +373,7 @@ function renderComparisonPlot(plotid, unit, benchmarks, exes, enviros, baseline,
286373 responsive : true ,
287374 maintainAspectRatio : false ,
288375 plugins : {
289- title : { display : true , text : title , font : { size : 15 } } ,
376+ title : { display : false } ,
290377 tooltip : { position : 'cursor' } ,
291378 legend : {
292379 position : 'right' ,
@@ -318,6 +405,7 @@ function renderComparisonPlot(plotid, unit, benchmarks, exes, enviros, baseline,
318405 }
319406 } ) ;
320407 chartInstances . push ( instance ) ;
408+ return title ;
321409}
322410
323411function init ( defaults ) {
@@ -371,7 +459,39 @@ function init(defaults) {
371459 loadData ( ) ;
372460
373461 $ ( "#permalink" ) . click ( function ( ) {
374- window . location = "?" + $ . param ( getConfiguration ( ) ) ;
462+ var conf = getConfiguration ( ) ;
463+ var $all = $ ( "input[name='benchmarks']" ) ;
464+ var $checked = $ ( "input[name='benchmarks']:checked" ) ;
465+ if ( $all . length > 0 && $all . length === $checked . length ) {
466+ conf . ben = 'all' ;
467+ } else {
468+ // Tally checked vs total per source
469+ var sources = { } ;
470+ $all . each ( function ( ) {
471+ var src = $ ( this ) . data ( 'source' ) ;
472+ if ( ! sources [ src ] ) { sources [ src ] = { total : 0 , checked : 0 } ; }
473+ sources [ src ] . total ++ ;
474+ if ( $ ( this ) . is ( ':checked' ) ) { sources [ src ] . checked ++ ; }
475+ } ) ;
476+ var full = Object . keys ( sources ) . filter ( function ( s ) {
477+ return sources [ s ] . checked === sources [ s ] . total ;
478+ } ) ;
479+ var empty = Object . keys ( sources ) . filter ( function ( s ) {
480+ return sources [ s ] . checked === 0 ;
481+ } ) ;
482+ // Use source aliases only when every source is either fully selected or fully empty
483+ if ( full . length + empty . length === Object . keys ( sources ) . length && full . length > 0 ) {
484+ conf . ben = full . join ( ',' ) ;
485+ }
486+ }
487+ var qs = Object . keys ( conf ) . map ( function ( k ) {
488+ return k + '=' + encodeURIComponent ( String ( conf [ k ] ) )
489+ . replace ( / % 2 C / gi, ',' )
490+ . replace ( / % 3 A / gi, ':' )
491+ . replace ( / % 4 0 / gi, '@' )
492+ . replace ( / % 2 0 / g, '+' ) ;
493+ } ) . join ( '&' ) ;
494+ window . location = '?' + qs ;
375495 } ) ;
376496
377497 $ ( "#exportcsv" ) . click ( function ( e ) {
@@ -386,7 +506,7 @@ function init(defaults) {
386506 var header = [ "benchmark" ] ;
387507 for ( var i = 0 ; i < exes . length ; i ++ ) {
388508 for ( var j = 0 ; j < enviros . length ; j ++ ) {
389- var exeLabel = $ ( "label[for='exe_" + exes [ i ] + "']" ) . text ( ) . trim ( ) ;
509+ var exeLabel = getExeLabel ( exes [ i ] ) ;
390510 var envLabel = $ ( "label[for='env_" + enviros [ j ] + "']" ) . text ( ) . trim ( ) ;
391511 header . push ( enviros . length > 1 ? exeLabel + "@" + envLabel : exeLabel ) ;
392512 }
0 commit comments