()
| 52 | * Therefore you shouldn't call it too often, like more than once per second. |
| 53 | */ |
| 54 | export async function getMemoryInfo(): Promise<MemoryInfo> { |
| 55 | const psTreePromised = util.promisify(psTree); |
| 56 | |
| 57 | // lambda does *not* have `ps` and other command line tools |
| 58 | // required to extract memory usage. |
| 59 | const isLambdaEnvironment = process.platform === 'linux' && !!process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE; |
| 60 | |
| 61 | const isDockerVar = !isLambdaEnvironment && (await isDocker()); |
| 62 | |
| 63 | let mainProcessBytes = -1; |
| 64 | let childProcessesBytes = 0; |
| 65 | |
| 66 | if (isLambdaEnvironment) { |
| 67 | // reported in bytes |
| 68 | mainProcessBytes = process.memoryUsage().rss; |
| 69 | |
| 70 | // https://stackoverflow.com/a/55914335/129415 |
| 71 | const memInfo = execSync('cat /proc/meminfo').toString(); |
| 72 | const values = memInfo.split(/[\n: ]/).filter((val) => val.trim()); |
| 73 | // /proc/meminfo reports in kb, not bytes, the total used memory is reported by meminfo |
| 74 | // subtract memory used by the main node process in order to infer memory used by any child processes |
| 75 | childProcessesBytes = +values[19] * 1000 - mainProcessBytes; |
| 76 | } else { |
| 77 | // Query both root and child processes |
| 78 | const processes = await psTreePromised(process.pid, true); |
| 79 | |
| 80 | processes.forEach((rec: Dictionary<string>) => { |
| 81 | // Skip the 'ps' or 'wmic' commands used by ps-tree to query the processes |
| 82 | if (rec.COMMAND === 'ps' || rec.COMMAND === 'WMIC.exe') { |
| 83 | return; |
| 84 | } |
| 85 | const bytes = parseInt(rec.RSS, 10); |
| 86 | // Obtain main process' memory separately |
| 87 | if (rec.PID === `${process.pid}`) { |
| 88 | mainProcessBytes = bytes; |
| 89 | return; |
| 90 | } |
| 91 | childProcessesBytes += bytes; |
| 92 | }); |
| 93 | } |
| 94 | |
| 95 | let totalBytes: number; |
| 96 | let usedBytes: number; |
| 97 | let freeBytes: number; |
| 98 | |
| 99 | if (isLambdaEnvironment) { |
| 100 | // memory size is defined in megabytes |
| 101 | totalBytes = parseInt(process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE!, 10) * 1000000; |
| 102 | usedBytes = mainProcessBytes + childProcessesBytes; |
| 103 | freeBytes = totalBytes - usedBytes; |
| 104 | |
| 105 | log.debug(`lambda size of ${totalBytes} with ${freeBytes} free bytes`); |
| 106 | } else if (isDockerVar) { |
| 107 | // When running inside Docker container, use container memory limits |
| 108 | |
| 109 | // Check whether cgroups V1 or V2 is used |
| 110 | let cgroupsVersion: keyof typeof MEMORY_FILE_PATHS.TOTAL = 'V1'; |
| 111 | try { |
no test coverage detected
searching dependent graphs…