@@ -8,7 +8,7 @@ import * as logger from '../logger'
88import { Timeout , CancellationError , waitUntil } from './timeoutUtils'
99import { PollingSet } from './pollingSet'
1010import { getLogger } from '../logger/logger'
11- import { telemetry } from '../telemetry'
11+ import { SystemResource , telemetry } from '../telemetry'
1212
1313export interface RunParameterContext {
1414 /** Reports an error parsed from the stdin/stdout streams. */
@@ -64,14 +64,18 @@ export interface ChildProcessResult {
6464export const eof = Symbol ( 'EOF' )
6565type pid = number
6666export 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'
6973}
7074export class ChildProcessTracker {
7175 static readonly pollingInterval : number = 10000 // Check usage every 10 seconds
7276 static readonly thresholds : ProcessStats = {
73- memory : 100 , // 100 MB
74- cpu : 50 ,
77+ memoryBytes : 100 * 1024 * 1024 , // 100 MB
78+ cpuPercent : 50 ,
7579 }
7680 readonly logger : logger . Logger
7781 static #instance: ChildProcessTracker
@@ -111,7 +115,7 @@ export class ChildProcessTracker {
111115 const threshold = ChildProcessTracker . thresholds [ resource ]
112116 return value > threshold
113117 }
114- const warn = ( resource : keyof ProcessStats , value : number ) => {
118+ const warn = ( resource : SystemResource , value : number ) => {
115119 telemetry . ide_childProcessWarning . run ( ( span ) => {
116120 this . logger . warn ( `Process ${ this . getProcessAsStr ( pid ) } exceeded ${ resource } threshold: ${ value } ` )
117121 span . record ( { systemResource : resource , childProcess : this . getProcessAsStr ( pid ) } )
@@ -127,9 +131,9 @@ export class ChildProcessTracker {
127131 this . logger . warn ( `Failed to get process stats for process with pid ${ pid } ` )
128132 return
129133 }
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 ] )
133137 }
134138 }
135139 }
@@ -190,7 +194,7 @@ export class ChildProcessTracker {
190194 }
191195 const usage = await this . getAllUsage ( )
192196 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`
194198 } , '' )
195199 this . logger . info ( `Active Subprocesses (${ this . size } active)\n${ logMsg } ` )
196200 } )
@@ -202,10 +206,10 @@ export class ChildProcessTracker {
202206 return process . platform === 'win32' ? getWindowsUsage ( ) : getUnixUsage ( )
203207 } catch ( e ) {
204208 this . logger . warn ( `Failed to get process stats for ${ pid } : ${ e } ` )
205- return { cpu : 0 , memory : 0 }
209+ return { cpuPercent : 0 , memoryBytes : 0 }
206210 }
207211
208- function getWindowsUsage ( ) {
212+ function getWindowsUsage ( ) : ProcessStats {
209213 const cpuOutput = proc
210214 . execFileSync ( 'wmic' , [
211215 'path' ,
@@ -224,12 +228,12 @@ export class ChildProcessTracker {
224228 const memoryBytes = parseInt ( memOutput . split ( '\n' ) [ 1 ] ) * 1024
225229
226230 return {
227- cpu : isNaN ( cpuPercentage ) ? 0 : cpuPercentage ,
228- memory : memoryBytes / ( 1024 * 1024 ) ,
231+ cpuPercent : isNaN ( cpuPercentage ) ? 0 : cpuPercentage ,
232+ memoryBytes,
229233 }
230234 }
231235
232- function getUnixUsage ( ) {
236+ function getUnixUsage ( ) : ProcessStats {
233237 const cpuMemOutput = proc . execFileSync ( 'ps' , [ '-p' , pid . toString ( ) , '-o' , '%cpu,%mem' ] ) . toString ( )
234238 const rssOutput = proc . execFileSync ( 'ps' , [ '-p' , pid . toString ( ) , '-o' , 'rss' ] ) . toString ( )
235239
@@ -238,16 +242,16 @@ export class ChildProcessTracker {
238242 const memoryBytes = parseInt ( rssOutput . split ( '\n' ) [ 1 ] ) * 1024
239243
240244 return {
241- cpu : isNaN ( cpuPercentage ) ? 0 : cpuPercentage ,
242- memory : memoryBytes / ( 1024 * 1024 ) ,
245+ cpuPercent : isNaN ( cpuPercentage ) ? 0 : cpuPercentage ,
246+ memoryBytes,
243247 }
244248 }
245249 }
246250}
247251
248252export interface ProcessStats {
249- memory : number
250- cpu : number
253+ memoryBytes : number
254+ cpuPercent : number
251255}
252256export class ChildProcess {
253257 static #runningProcesses = ChildProcessTracker . instance
0 commit comments