@@ -8,7 +8,7 @@ import * as logger from '../logger'
8
8
import { Timeout , CancellationError , waitUntil } from './timeoutUtils'
9
9
import { PollingSet } from './pollingSet'
10
10
import { getLogger } from '../logger/logger'
11
- import { telemetry } from '../telemetry'
11
+ import { SystemResource , telemetry } from '../telemetry'
12
12
13
13
export interface RunParameterContext {
14
14
/** Reports an error parsed from the stdin/stdout streams. */
@@ -64,14 +64,18 @@ export interface ChildProcessResult {
64
64
export const eof = Symbol ( 'EOF' )
65
65
type pid = number
66
66
export interface ProcessStats {
67
- memory : number
68
- cpu : number
67
+ memoryBytes : number
68
+ cpuPercent : number
69
+ }
70
+
71
+ function toTelemetryResource ( k : keyof ProcessStats ) : SystemResource {
72
+ return k === 'cpuPercent' ? 'cpu' : 'memory'
69
73
}
70
74
export class ChildProcessTracker {
71
75
static readonly pollingInterval : number = 10000 // Check usage every 10 seconds
72
76
static readonly thresholds : ProcessStats = {
73
- memory : 100 , // 100 MB
74
- cpu : 50 ,
77
+ memoryBytes : 100 * 1024 * 1024 , // 100 MB
78
+ cpuPercent : 50 ,
75
79
}
76
80
readonly logger : logger . Logger
77
81
static #instance: ChildProcessTracker
@@ -111,7 +115,7 @@ export class ChildProcessTracker {
111
115
const threshold = ChildProcessTracker . thresholds [ resource ]
112
116
return value > threshold
113
117
}
114
- const warn = ( resource : keyof ProcessStats , value : number ) => {
118
+ const warn = ( resource : SystemResource , value : number ) => {
115
119
telemetry . ide_childProcessWarning . run ( ( span ) => {
116
120
this . logger . warn ( `Process ${ this . getProcessAsStr ( pid ) } exceeded ${ resource } threshold: ${ value } ` )
117
121
span . record ( { systemResource : resource , childProcess : this . getProcessAsStr ( pid ) } )
@@ -127,9 +131,9 @@ export class ChildProcessTracker {
127
131
this . logger . warn ( `Failed to get process stats for process with pid ${ pid } ` )
128
132
return
129
133
}
130
- for ( const resource of Object . keys ( ChildProcessTracker . thresholds ) as ( keyof ProcessStats ) [ ] ) {
131
- if ( doesExceedThreshold ( resource , stats [ resource ] ) ) {
132
- warn ( resource as keyof ProcessStats , stats [ resource ] )
134
+ for ( const processStat of Object . keys ( ChildProcessTracker . thresholds ) as ( keyof ProcessStats ) [ ] ) {
135
+ if ( doesExceedThreshold ( processStat , stats [ processStat ] ) ) {
136
+ warn ( toTelemetryResource ( processStat ) , stats [ processStat ] )
133
137
}
134
138
}
135
139
}
@@ -190,7 +194,7 @@ export class ChildProcessTracker {
190
194
}
191
195
const usage = await this . getAllUsage ( )
192
196
const logMsg = Array . from ( usage . entries ( ) ) . reduce ( ( acc , [ pid , stats ] ) => {
193
- return acc + `Process ${ pid } : ${ stats . cpu } % cpu, ${ stats . memory } MB of memory\n`
197
+ return acc + `Process ${ pid } : ${ stats . cpuPercent } % cpu, ${ stats . memoryBytes } B of memory\n`
194
198
} , '' )
195
199
this . logger . info ( `Active Subprocesses (${ this . size } active)\n${ logMsg } ` )
196
200
} )
@@ -202,10 +206,10 @@ export class ChildProcessTracker {
202
206
return process . platform === 'win32' ? getWindowsUsage ( ) : getUnixUsage ( )
203
207
} catch ( e ) {
204
208
this . logger . warn ( `Failed to get process stats for ${ pid } : ${ e } ` )
205
- return { cpu : 0 , memory : 0 }
209
+ return { cpuPercent : 0 , memoryBytes : 0 }
206
210
}
207
211
208
- function getWindowsUsage ( ) {
212
+ function getWindowsUsage ( ) : ProcessStats {
209
213
const cpuOutput = proc
210
214
. execFileSync ( 'wmic' , [
211
215
'path' ,
@@ -224,12 +228,12 @@ export class ChildProcessTracker {
224
228
const memoryBytes = parseInt ( memOutput . split ( '\n' ) [ 1 ] ) * 1024
225
229
226
230
return {
227
- cpu : isNaN ( cpuPercentage ) ? 0 : cpuPercentage ,
228
- memory : memoryBytes / ( 1024 * 1024 ) ,
231
+ cpuPercent : isNaN ( cpuPercentage ) ? 0 : cpuPercentage ,
232
+ memoryBytes,
229
233
}
230
234
}
231
235
232
- function getUnixUsage ( ) {
236
+ function getUnixUsage ( ) : ProcessStats {
233
237
const cpuMemOutput = proc . execFileSync ( 'ps' , [ '-p' , pid . toString ( ) , '-o' , '%cpu,%mem' ] ) . toString ( )
234
238
const rssOutput = proc . execFileSync ( 'ps' , [ '-p' , pid . toString ( ) , '-o' , 'rss' ] ) . toString ( )
235
239
@@ -238,16 +242,16 @@ export class ChildProcessTracker {
238
242
const memoryBytes = parseInt ( rssOutput . split ( '\n' ) [ 1 ] ) * 1024
239
243
240
244
return {
241
- cpu : isNaN ( cpuPercentage ) ? 0 : cpuPercentage ,
242
- memory : memoryBytes / ( 1024 * 1024 ) ,
245
+ cpuPercent : isNaN ( cpuPercentage ) ? 0 : cpuPercentage ,
246
+ memoryBytes,
243
247
}
244
248
}
245
249
}
246
250
}
247
251
248
252
export interface ProcessStats {
249
- memory : number
250
- cpu : number
253
+ memoryBytes : number
254
+ cpuPercent : number
251
255
}
252
256
export class ChildProcess {
253
257
static #runningProcesses = ChildProcessTracker . instance
0 commit comments