!7 sclass Process { S processID, name, commandLine; long residentSize; double cpuUsage; // percent per core sS _fieldOrder = "processID name commandLine residentSize cpuUsage"; } cm ProcessList > DynObjectTable { switchable bool showTiming; switchable double interval = 3.0; switchable double firstInterval = 1.0; switchable bool sortBySize; start { dontPersist(); itemToMap = func(Process p) -> Map { humanizeKeys( applyFunctionToMapValue('cpuUsage, f iround_spacePercentSign, applyFunctionToMapValue('residentSize, f str_toM, objectToMap_honorFieldOrder(p)))) }; actualUpdate(); // to make sort keys work dm_doEvery(firstInterval, interval, r actualUpdate); dm_reloadOnFieldChange interval(); dm_reloadOnFieldChange sortBySize(); } afterVisualize { addRowSorter_desc(table, sortBySize ? 3 : 4); // Resident Size / CPU rowSorter_setComparators(table, 3, alphaNumComparator(), 2, alphaNumComparator(), 4, alphaNumComparator()); swing { ((DefaultRowSorter) table.getRowSorter()).sort(); } tablePopupMenuItem(table(), "Kill!", rThread { killProcess(selected().processID) }); } void actualUpdate enter { L list = timedIf(showTiming, func -> L { oshi_listProcesses_withoutOpenFiles() }); setData(map(list, func(OSProcess p) -> Process { nu(Process, processID := str(p.getProcessID()), name := p.getName(), commandLine := p.getCommandLine(), residentSize := p.getResidentSetSize(), cpuUsage := oshi_calcProcessCPUUsage_v2(p)) })); } }