Skip to content

Commit

Permalink
Show CPU and memory usage in interactive mode (#63)
Browse files Browse the repository at this point in the history
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
  • Loading branch information
Yanis Benson and sindresorhus authored Feb 12, 2020
1 parent 33e6e86 commit 45e1e1d
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 5 deletions.
4 changes: 3 additions & 1 deletion cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ const cli = meow(`
To kill a port, prefix it with a colon. For example: :8080.
Run without arguments to use the interactive interface.
Run without arguments to use the interactive mode.
In interactive mode, 🚦A.B% indicates high CPU usage, 🐏C.D% indicates high memory usage.
The process name is case insensitive.
`, {
inferType: true,
Expand Down
49 changes: 45 additions & 4 deletions interactive.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,69 @@ const nameFilter = (input, proc) => {
return proc.name.toLowerCase().includes(input.toLowerCase());
};

const preferNotMatching = matches => (a, b) => {
const aMatches = matches(a);
return matches(b) === aMatches ? 0 : (aMatches ? 1 : -1);
};

const deprioritizedProcesses = new Set(['iTerm', 'iTerm2', 'fkill']);
const isDeprioritizedProcess = proc => deprioritizedProcesses.has(proc.name);
const preferNotDeprioritized = preferNotMatching(isDeprioritizedProcess);
const preferHighPerformanceImpact = (a, b) => numSort.desc(a.cpu + a.memory, b.cpu + b.memory);
const preferLowAlphanumericNames = (a, b) => a.name.localeCompare(b.name);

const preferHeurisicallyInterestingProcesses = (a, b) => {
let result;

result = preferNotDeprioritized(a, b);
if (result !== 0) {
return result;
}

result = preferHighPerformanceImpact(a, b);
if (result !== 0) {
return result;
}

return preferLowAlphanumericNames(a, b);
};

const filterProcesses = (input, processes, flags) => {
const filters = {
name: proc => input ? nameFilter(input, proc) : true,
verbose: proc => input ? (process.platform === 'win32' ? proc.name : proc.cmd).toLowerCase().includes(input.toLowerCase()) : true
};

const memoryThreshold = flags.verbose ? 0.0 : 1.0;
const cpuThreshold = flags.verbose ? 0.0 : 3.0;

return processes
.filter(proc => !(
proc.name.endsWith('-helper') ||
proc.name.endsWith('Helper') ||
proc.name.endsWith('HelperApp')
))
.filter(flags.verbose ? filters.verbose : filters.name)
.sort((a, b) => numSort.asc(a.pid, b.pid))
.sort(preferHeurisicallyInterestingProcesses)
.map(proc => {
const renderPercentage = percents => {
const digits = Math.floor(percents * 10).toString().padStart(2, '0');
const whole = digits.substr(0, digits.length - 1);
const fraction = digits.substr(digits.length - 1);
return fraction === '0' ? `${whole}%` : `${whole}.${fraction}%`;
};

const lineLength = process.stdout.columns || 80;
const ports = proc.ports.slice(0, 4).map(x => `:${x}`).join(' ').trim();
const margins = commandLineMargins + proc.pid.toString().length + ports.length;
const ports = proc.ports.length === 0 ? '' : (' ' + proc.ports.slice(0, 4).map(x => `:${x}`).join(' '));
const memory = (proc.memory !== undefined && (proc.memory > memoryThreshold)) ? ` 🐏${renderPercentage(proc.memory)}` : '';
const cpu = (proc.cpu !== undefined && (proc.cpu > cpuThreshold)) ? `🚦${renderPercentage(proc.cpu)}` : '';
const margins = commandLineMargins + proc.pid.toString().length + ports.length + memory.length + cpu.length;
const length = lineLength - margins;
const name = cliTruncate(flags.verbose && process.platform !== 'win32' ? proc.cmd : proc.name, length, {position: 'middle'});
const spacer = lineLength === process.stdout.columns ? ''.padEnd(length - name.length) : '';

return {
name: `${name} ${chalk.dim(proc.pid)} ${chalk.dim.magenta(ports)}`,
name: `${name} ${chalk.dim(proc.pid)}${spacer}${chalk.dim(ports)}${cpu}${memory}`,
value: proc.pid
};
});
Expand Down Expand Up @@ -107,6 +147,7 @@ const init = async flags => {
pidFromPort.list(),
psList({all: false})
]);

const procs = processes.map(proc => ({...proc, ports: getPortsFromPid(proc.pid, pids)}));
listProcesses(procs, flags);
};
Expand Down

0 comments on commit 45e1e1d

Please sign in to comment.