113113 .grid {
114114 display : grid;
115115 gap : 12px ;
116- grid-template-columns : repeat (4 , minmax (160px , 1fr ));
116+ grid-template-columns : repeat (5 , minmax (160px , 1fr ));
117117 }
118118
119119 label {
@@ -488,6 +488,14 @@ <h1>Max Memory Summary Viewer</h1>
488488 < option value ="adiff-asc "> PR - baseline ascending</ option >
489489 </ select >
490490 </ div >
491+ < div >
492+ < label for ="aggregationSelect "> Aggregation</ label >
493+ < select id ="aggregationSelect ">
494+ < option value ="max " selected > max</ option >
495+ < option value ="min "> min</ option >
496+ < option value ="abs-max "> abs(max)</ option >
497+ </ select >
498+ </ div >
491499 < label class ="checkbox " for ="hideZeroRows ">
492500 < input id ="hideZeroRows " type ="checkbox ">
493501 Hide workflows with only zero values
@@ -553,13 +561,20 @@ <h1>Max Memory Summary Viewer</h1>
553561 { key : "pdiff" , label : "100 * (PR - baseline) / baseline" , unit : "%" }
554562 ] ;
555563
564+ const AGGREGATIONS = [
565+ { key : "max" , label : "max" } ,
566+ { key : "min" , label : "min" } ,
567+ { key : "abs-max" , label : "abs(max)" }
568+ ] ;
569+
556570 const state = {
557571 payload : null ,
558572 workflows : [ ] ,
559573 steps : [ ] ,
560574 search : "" ,
561575 quantityKey : "max memory" ,
562576 sortKey : "workflow-asc" ,
577+ aggregationKey : "max" ,
563578 expandedWorkflows : new Set ( ) ,
564579 detailSortKey : "step" ,
565580 detailSortDir : "asc"
@@ -569,6 +584,7 @@ <h1>Max Memory Summary Viewer</h1>
569584 workflowSearch : document . getElementById ( "workflowSearch" ) ,
570585 quantitySelect : document . getElementById ( "quantitySelect" ) ,
571586 sortSelect : document . getElementById ( "sortSelect" ) ,
587+ aggregationSelect : document . getElementById ( "aggregationSelect" ) ,
572588 hideZeroRows : document . getElementById ( "hideZeroRows" ) ,
573589 loadedCount : document . getElementById ( "loadedCount" ) ,
574590 visibleCount : document . getElementById ( "visibleCount" ) ,
@@ -613,6 +629,20 @@ <h1>Max Memory Summary Viewer</h1>
613629 return `${ quantityKey } ${ legendKey } ` ;
614630 }
615631
632+ function currentAggregation ( ) {
633+ return AGGREGATIONS . find ( ( aggregation ) => aggregation . key === state . aggregationKey ) || AGGREGATIONS [ 0 ] ;
634+ }
635+
636+ function aggregatedNumericValue ( value ) {
637+ if ( typeof value !== "number" || Number . isNaN ( value ) ) {
638+ return value ;
639+ }
640+ if ( state . aggregationKey === "abs-max" ) {
641+ return Math . abs ( value ) ;
642+ }
643+ return value ;
644+ }
645+
616646 function formatValue ( value , quantity , legend ) {
617647 if ( value === undefined || value === null || Number . isNaN ( value ) ) {
618648 return "-" ;
@@ -690,7 +720,7 @@ <h1>Max Memory Summary Viewer</h1>
690720 case "pdiff-asc" : {
691721 const legendKey = state . sortKey . split ( "-" ) [ 0 ] ;
692722 const sortField = fieldName ( currentQuantity ( ) . key , legendKey ) ;
693- return compareMaybeNumbers ( maxStepValue ( left , sortField ) . value , maxStepValue ( right , sortField ) . value )
723+ return compareMaybeNumbers ( aggregateStepValue ( left , sortField ) . value , aggregateStepValue ( right , sortField ) . value )
694724 || workflowNumber ( left . name ) - workflowNumber ( right . name )
695725 || left . name . localeCompare ( right . name ) ;
696726 }
@@ -700,7 +730,7 @@ <h1>Max Memory Summary Viewer</h1>
700730 case "pdiff-desc" : {
701731 const legendKey = state . sortKey . split ( "-" ) [ 0 ] ;
702732 const sortField = fieldName ( currentQuantity ( ) . key , legendKey ) ;
703- return compareMaybeNumbers ( maxStepValue ( right , sortField ) . value , maxStepValue ( left , sortField ) . value )
733+ return compareMaybeNumbers ( aggregateStepValue ( right , sortField ) . value , aggregateStepValue ( left , sortField ) . value )
704734 || workflowNumber ( left . name ) - workflowNumber ( right . name )
705735 || left . name . localeCompare ( right . name ) ;
706736 }
@@ -731,7 +761,7 @@ <h1>Max Memory Summary Viewer</h1>
731761 renderTable ( ) ;
732762 }
733763
734- function maxStepValue ( row , selectedField ) {
764+ function aggregateStepValue ( row , selectedField ) {
735765 let bestValue = null ;
736766 let bestStepData = null ;
737767
@@ -741,7 +771,30 @@ <h1>Max Memory Summary Viewer</h1>
741771 if ( typeof value !== "number" || Number . isNaN ( value ) ) {
742772 continue ;
743773 }
744- if ( bestValue === null || value > bestValue ) {
774+
775+ if ( bestValue === null ) {
776+ bestValue = value ;
777+ bestStepData = stepData ;
778+ continue ;
779+ }
780+
781+ if ( state . aggregationKey === "min" ) {
782+ if ( value < bestValue ) {
783+ bestValue = value ;
784+ bestStepData = stepData ;
785+ }
786+ continue ;
787+ }
788+
789+ if ( state . aggregationKey === "abs-max" ) {
790+ if ( Math . abs ( value ) > Math . abs ( bestValue ) ) {
791+ bestValue = Math . abs ( value ) ;
792+ bestStepData = stepData ;
793+ }
794+ continue ;
795+ }
796+
797+ if ( value > bestValue ) {
745798 bestValue = value ;
746799 bestStepData = stepData ;
747800 }
@@ -821,10 +874,10 @@ <h1>Max Memory Summary Viewer</h1>
821874 workflow : workflowName ,
822875 step,
823876 stepOrder : stepNumber ( step ) ,
824- baseline : stepData [ fieldName ( quantity . key , "base" ) ] ,
825- pullRequest : stepData [ fieldName ( quantity . key , "pr" ) ] ,
826- absoluteDiff : stepData [ fieldName ( quantity . key , "adiff" ) ] ,
827- percentDiff : stepData [ fieldName ( quantity . key , "pdiff" ) ]
877+ baseline : aggregatedNumericValue ( stepData [ fieldName ( quantity . key , "base" ) ] ) ,
878+ pullRequest : aggregatedNumericValue ( stepData [ fieldName ( quantity . key , "pr" ) ] ) ,
879+ absoluteDiff : aggregatedNumericValue ( stepData [ fieldName ( quantity . key , "adiff" ) ] ) ,
880+ percentDiff : aggregatedNumericValue ( stepData [ fieldName ( quantity . key , "pdiff" ) ] )
828881 } ;
829882 } ) ;
830883
@@ -880,6 +933,7 @@ <h1>Max Memory Summary Viewer</h1>
880933
881934 function buildDetailTable ( workflowName , steps ) {
882935 const quantity = currentQuantity ( ) ;
936+ const aggregation = currentAggregation ( ) ;
883937 const detailRows = getDetailRows ( workflowName , steps ) ;
884938 const percentLegend = LEGENDS . find ( ( legend ) => legend . key === "pdiff" ) ;
885939 const numberLegend = { key : "base" , unit : quantity . unit } ;
@@ -892,10 +946,10 @@ <h1>Max Memory Summary Viewer</h1>
892946 <tr>
893947 <th class="sortable" data-sort-key="workflow">Workflow${ detailSortIndicator ( "workflow" ) } </th>
894948 <th class="sortable" data-sort-key="step">Step${ detailSortIndicator ( "step" ) } </th>
895- <th class="sortable th-num" data-sort-key="baseline">Baseline${ detailSortIndicator ( "baseline" ) } </th>
896- <th class="sortable th-num" data-sort-key="pullRequest">Pull Request${ detailSortIndicator ( "pullRequest" ) } </th>
897- <th class="sortable th-num" data-sort-key="absoluteDiff">PR - Baseline${ detailSortIndicator ( "absoluteDiff" ) } </th>
898- <th class="sortable th-num" data-sort-key="percentDiff">Percent Diff${ detailSortIndicator ( "percentDiff" ) } </th>
949+ <th class="sortable th-num" data-sort-key="baseline">Baseline ( ${ aggregation . label } ) ${ detailSortIndicator ( "baseline" ) } </th>
950+ <th class="sortable th-num" data-sort-key="pullRequest">Pull Request ( ${ aggregation . label } ) ${ detailSortIndicator ( "pullRequest" ) } </th>
951+ <th class="sortable th-num" data-sort-key="absoluteDiff">PR - Baseline ( ${ aggregation . label } ) ${ detailSortIndicator ( "absoluteDiff" ) } </th>
952+ <th class="sortable th-num" data-sort-key="percentDiff">Percent Diff ( ${ aggregation . label } ) ${ detailSortIndicator ( "percentDiff" ) } </th>
899953 </tr>
900954 </thead>
901955 <tbody>
@@ -934,6 +988,7 @@ <h1>Max Memory Summary Viewer</h1>
934988 const rows = getWorkflowRows ( ) ;
935989 const peak = peakSignal ( rows , selectedField ) ;
936990 const adiffLegend = LEGENDS . find ( ( legend ) => legend . key === "adiff" ) || LEGENDS [ 0 ] ;
991+ const aggregation = currentAggregation ( ) ;
937992
938993 el . loadedCount . textContent = state . workflows . length . toLocaleString ( ) ;
939994 el . visibleCount . textContent = rows . length . toLocaleString ( ) ;
@@ -957,7 +1012,7 @@ <h1>Max Memory Summary Viewer</h1>
9571012 const legendHead = document . createElement ( "th" ) ;
9581013 legendHead . className = "sortable th-num" ;
9591014 legendHead . setAttribute ( "data-sort-key" , legend . key ) ;
960- legendHead . textContent = `${ legend . label } (max )${ mainSortIndicator ( legend . key ) } ` ;
1015+ legendHead . textContent = `${ legend . label } (${ aggregation . label } )${ mainSortIndicator ( legend . key ) } ` ;
9611016 el . tableHeadRow . appendChild ( legendHead ) ;
9621017 }
9631018
@@ -985,7 +1040,7 @@ <h1>Max Memory Summary Viewer</h1>
9851040
9861041 for ( const legend of LEGENDS ) {
9871042 const legendField = fieldName ( quantity . key , legend . key ) ;
988- const maxValue = maxStepValue ( row , legendField ) ;
1043+ const maxValue = aggregateStepValue ( row , legendField ) ;
9891044 const maxValueCell = document . createElement ( "td" ) ;
9901045 maxValueCell . className = cellClass ( quantity , legend , maxValue . stepData , maxValue . value ) ;
9911046 maxValueCell . textContent = formatValue ( maxValue . value , quantity , legend ) ;
@@ -1014,7 +1069,7 @@ <h1>Max Memory Summary Viewer</h1>
10141069 } ) ;
10151070 attachDetailSortHandlers ( ) ;
10161071
1017- setStatus ( `Showing ${ rows . length . toLocaleString ( ) } workflows for ${ quantity . label } , sorted by ${ mainSortColumn ( ) === "workflow" ? "workflow" : mainSortColumn ( ) + " max" } .` , false ) ;
1072+ setStatus ( `Showing ${ rows . length . toLocaleString ( ) } workflows for ${ quantity . label } , sorted by ${ mainSortColumn ( ) === "workflow" ? "workflow" : mainSortColumn ( ) + " " + aggregation . label } .` , false ) ;
10181073 }
10191074
10201075 function populateSelectors ( ) {
@@ -1023,6 +1078,10 @@ <h1>Max Memory Summary Viewer</h1>
10231078 . join ( "" ) ;
10241079 el . quantitySelect . value = state . quantityKey ;
10251080 el . sortSelect . value = state . sortKey ;
1081+ el . aggregationSelect . innerHTML = AGGREGATIONS
1082+ . map ( ( aggregation ) => `<option value="${ escapeHtml ( aggregation . key ) } ">${ escapeHtml ( aggregation . label ) } </option>` )
1083+ . join ( "" ) ;
1084+ el . aggregationSelect . value = state . aggregationKey ;
10261085 }
10271086
10281087 function attachEvents ( ) {
@@ -1041,6 +1100,11 @@ <h1>Max Memory Summary Viewer</h1>
10411100 renderTable ( ) ;
10421101 } ) ;
10431102
1103+ el . aggregationSelect . addEventListener ( "change" , ( ) => {
1104+ state . aggregationKey = el . aggregationSelect . value ;
1105+ renderTable ( ) ;
1106+ } ) ;
1107+
10441108 el . hideZeroRows . addEventListener ( "change" , ( ) => {
10451109 renderTable ( ) ;
10461110 } ) ;
0 commit comments