@@ -16,7 +16,7 @@ import { CSS, React, Rendered, useRedux } from "@cocalc/frontend/app-framework";
16
16
import { Icon , r_join } from "@cocalc/frontend/components" ;
17
17
import Stopwatch from "@cocalc/frontend/editors/stopwatch/stopwatch" ;
18
18
import { webapp_client } from "@cocalc/frontend/webapp-client" ;
19
- import { path_split , tail } from "@cocalc/util/misc" ;
19
+ import { path_split , tail , unreachable } from "@cocalc/util/misc" ;
20
20
import { COLORS } from "@cocalc/util/theme" ;
21
21
import {
22
22
ExecuteCodeOutput ,
@@ -99,16 +99,40 @@ export const Build: React.FC<Props> = React.memo((props) => {
99
99
} ) ;
100
100
}
101
101
102
- function getMaxMem ( stats ?: ExecuteCodeOutputAsync [ "stats" ] ) : string {
103
- if ( Array . isArray ( stats ) && stats . length > 0 ) {
104
- const max_mem = stats . reduce ( ( cur , val ) => {
105
- return val . mem_rss > cur ? val . mem_rss : cur ;
106
- } , 0 ) ;
107
- // if there is no data (too many processes, etc.) then it is 0.
108
- // That information is misleading and we ignore it
109
- if ( max_mem > 0 ) {
110
- return ` Memory usage: ${ max_mem . toFixed ( 0 ) } MB.` ;
102
+ function getResourceUsage (
103
+ stats : ExecuteCodeOutputAsync [ "stats" ] | undefined ,
104
+ type : "peak" | "last" ,
105
+ ) : string {
106
+ if ( ! Array . isArray ( stats ) || stats . length === 0 ) {
107
+ return "" ;
108
+ }
109
+
110
+ switch ( type ) {
111
+ // This is after the job finished. We return the CPU time used and max memory.
112
+ case "peak" : {
113
+ const max_mem = stats . reduce ( ( cur , val ) => {
114
+ return val . mem_rss > cur ? val . mem_rss : cur ;
115
+ } , 0 ) ;
116
+ // if there is no data (too many processes, etc.) then it is 0.
117
+ // That information is misleading and we ignore it
118
+ if ( max_mem > 0 ) {
119
+ return ` Peak memory usage: ${ max_mem . toFixed ( 0 ) } MB.` ;
120
+ }
121
+ break ;
122
+ }
123
+
124
+ // This is while the log updates come in: last known CPU in % and memory usage.
125
+ case "last" : {
126
+ const { mem_rss, cpu_pct } = stats . slice ( - 1 ) [ 0 ] ;
127
+ if ( mem_rss > 0 || cpu_pct > 0 ) {
128
+ return ` Resource usage: ${ mem_rss . toFixed (
129
+ 0 ,
130
+ ) } MB memory and ${ cpu_pct . toFixed ( 0 ) } % CPU.`;
131
+ }
132
+ break ;
111
133
}
134
+ default :
135
+ unreachable ( type ) ;
112
136
}
113
137
return "" ;
114
138
}
@@ -130,7 +154,7 @@ export const Build: React.FC<Props> = React.memo((props) => {
130
154
if ( typeof elapsed_s === "number" && elapsed_s > 0 ) {
131
155
job_info_str = `Build time: ${ elapsed_s . toFixed ( 1 ) } seconds.` ;
132
156
}
133
- job_info_str += getMaxMem ( stats ) ;
157
+ job_info_str += getResourceUsage ( stats , "peak" ) ;
134
158
}
135
159
const title = BUILD_SPECS [ stage ] . label ;
136
160
// highlights tab, if there is at least one parsed error
@@ -209,7 +233,7 @@ export const Build: React.FC<Props> = React.memo((props) => {
209
233
build_logs . forEach ( ( infoI , key ) => {
210
234
const info : ExecuteCodeOutput = infoI ?. toJS ( ) ;
211
235
if ( ! info || info . type !== "async" || info . status !== "running" ) return ;
212
- const stats_str = getMaxMem ( info . stats ) ;
236
+ const stats_str = getResourceUsage ( info . stats , "last" ) ;
213
237
const start = info . start ;
214
238
logTail = tail ( info . stdout ?? "" + info . stderr ?? "" , 6 ) ;
215
239
isLongRunning ||=
0 commit comments