@@ -142,41 +142,55 @@ class StatsCommand extends BpipeCommand {
142142 List<List > stats = doms. collect { dom -> dom. commands. command }. sum(). groupBy { cmdNode ->
143143 cmdNode. stage. text()
144144 }. collect { stage , cmds ->
145-
145+
146146 // Failed commands do not accurately reflect the time taken, so
147147 // only count commands that succeeded
148148 List succeeded = cmds. grep { cmd ->
149149 cmd. exitCode. text() == " 0"
150150 }
151-
151+
152152 List valid = succeeded. grep { cmd ->
153153 // Bug where start times not initialised can have caused historical entries to have this
154154 ! cmd. start. text(). startsWith(' 1970' )
155155 }
156-
156+
157157 if (valid. isEmpty()) {
158158 return null
159159 }
160160
161- List<Long > times = valid. collect { cmd ->
162- long startTimeMs = toDate(cmd. start). time
161+ List<Long > times = valid. collect { cmd ->
162+ long startTimeMs = toDate(cmd. start). time
163163 startTimeMs == 0 ? 0 : toDate(cmd. end). time - startTimeMs
164164 }
165-
165+
166166 List<Long > startTimes = valid. collect { cmd -> def t = toDate(cmd. start). time; return t; }
167167 long minStart = startTimes. min()
168168 long minStartRel = minStart != null ? minStart - pipelineStartTimeMs : -1
169- long maxEnd = valid. collect { cmd ->
169+ long maxEnd = valid. collect { cmd ->
170170 long startTimeMs = toDate(cmd. start). time;
171171 return startTimeMs == 0 ? 0 : toDate(cmd. end). time
172- }. max() - pipelineStartTimeMs
173-
172+ }. max() - pipelineStartTimeMs
173+
174174 double mean = times. isEmpty() ? 0 : times. sum() / times. size()
175175
176176 String timing = (minStartRel < 0 ) ? ' ' : formatTimingBar(minStartRel, maxEnd, pipelineTotalMs, 60 )
177177
178178 def cores = valid. collect { cmd -> cmd. resources?. procs }. find { it }?: " -"
179179
180+ // Utilisation: mean cores used across instances
181+ List<Double > coresUsedVals = valid. collect { cmd ->
182+ String cu = cmd. utilisation?. coresUsed?. text()
183+ (cu && cu. isDouble()) ? cu. toDouble() : null
184+ }. findAll { it != null }
185+ String used = coresUsedVals ? String . format(' %.1f' , coresUsedVals. sum() / coresUsedVals. size()) : ' -'
186+
187+ // Peak memory: max across instances
188+ List<Long > rssVals = valid. collect { cmd ->
189+ String rss = cmd. utilisation?. maxRssBytes?. text()
190+ (rss && rss. isLong()) ? rss. toLong() : null
191+ }. findAll { it != null }
192+ String peakMem = rssVals ? Utils . humanBytes(rssVals. max()) : ' -'
193+
180194 List<Long > instanceBytes = valid. collect { sumInputBytes(it) }. findAll { it != null }
181195 String inputs = instanceBytes ? Utils . humanBytes((Long )instanceBytes. sum()) : ' -'
182196
@@ -186,14 +200,16 @@ class StatsCommand extends BpipeCommand {
186200 formatTimeSpan(times. min()?. toLong()),
187201 formatTimeSpan(mean), formatTimeSpan(times. max()),
188202 cores,
203+ used,
204+ peakMem,
189205 ((times. sum()?: 0 ) / 1000.0 ). toLong(),
190206 inputs,
191207 timing
192208 ]
193209 }
194210 .grep { it != null }
195211
196- Utils . table([" Stage" ," Count" ," Min" ," Mean" ," Max" , " Cores" ," Weight" ," Inputs" ," Timing" ], stats, indent :1 )
212+ Utils . table([" Stage" ," Count" ," Min" ," Mean" ," Max" , " Cores" ," Used " , " Peak Mem " , " Weight" ," Inputs" ," Timing" ], stats, indent :1 )
197213
198214 out. println " "
199215 }
@@ -287,6 +303,13 @@ class StatsCommand extends BpipeCommand {
287303
288304 String branch = cmd. branch. text() ?: ' -'
289305 String cores = cmd. resources?. procs?. text() ?: ' -'
306+
307+ // Utilisation columns
308+ String cuText = cmd. utilisation?. coresUsed?. text()
309+ String used = (cuText && cuText. isDouble()) ? String . format(' %.1f' , cuText. toDouble()) : ' -'
310+ String rssText = cmd. utilisation?. maxRssBytes?. text()
311+ String peakMem = (rssText && rssText. isLong()) ? Utils . humanBytes(rssText. toLong()) : ' -'
312+
290313 String exit = inProgress ? ' …' : exitText
291314 String duration = inProgress ? (formatTimeSpan(durMs) + ' +' ) : formatTimeSpan(durMs)
292315 Long instanceBytes = sumInputBytes(cmd)
@@ -299,13 +322,13 @@ class StatsCommand extends BpipeCommand {
299322
300323 String timing = formatTimingBar(startRel, endRel, pipelineTotalMs, 60 )
301324
302- return [branch, formatTimeSpan(startRel), duration, cores, inputs, exit, timing, commandPreview]
325+ return [branch, formatTimeSpan(startRel), duration, cores, used, peakMem, inputs, exit, timing, commandPreview]
303326 }
304327
305328 out. println " "
306329 out. println " Stage: ${ stageName} — ${ matching.size()} instance${ matching.size() == 1 ? '' : 's'} "
307330 out. println " "
308331
309- Utils . table([" Branch" ," Start" ," Duration" ," Cores" ," Inputs" ," Exit" ," Timing" ," Command" ], rows, indent :1 )
332+ Utils . table([" Branch" ," Start" ," Duration" ," Cores" ," Used " , " Peak Mem " , " Inputs" ," Exit" ," Timing" ," Command" ], rows, indent :1 )
310333 }
311334}
0 commit comments