From 2999fff88eef0cad39dbbc0054bdf8af9a92215e Mon Sep 17 00:00:00 2001 From: Benny Baumann Date: Sun, 29 May 2022 23:03:56 +0200 Subject: [PATCH] Refactor code for rendering command line cache Fixes #1008 --- AvailableMetersPanel.c | 1 + ColorsPanel.c | 1 + DisplayOptionsPanel.c | 1 + HeaderOptionsPanel.c | 1 + MetersPanel.c | 1 + Process.c | 56 +++++++++++++--------------------------- Process.h | 9 +------ ScreensPanel.c | 1 + Settings.c | 2 ++ Settings.h | 1 + linux/LinuxProcessList.c | 6 +++-- 11 files changed, 32 insertions(+), 48 deletions(-) diff --git a/AvailableMetersPanel.c b/AvailableMetersPanel.c index ae289ec42..368f494fb 100644 --- a/AvailableMetersPanel.c +++ b/AvailableMetersPanel.c @@ -79,6 +79,7 @@ static HandlerResult AvailableMetersPanel_eventHandler(Panel* super, int ch) { } if (update) { this->settings->changed = true; + this->settings->lastUpdate++; Header_calculateHeight(header); Header_updateData(header); Header_draw(header); diff --git a/ColorsPanel.c b/ColorsPanel.c index 50188f66e..590088423 100644 --- a/ColorsPanel.c +++ b/ColorsPanel.c @@ -68,6 +68,7 @@ static HandlerResult ColorsPanel_eventHandler(Panel* super, int ch) { this->settings->colorScheme = mark; this->settings->changed = true; + this->settings->lastUpdate++; CRT_setColors(mark); clear(); diff --git a/DisplayOptionsPanel.c b/DisplayOptionsPanel.c index 7688e7c76..fc23cb65e 100644 --- a/DisplayOptionsPanel.c +++ b/DisplayOptionsPanel.c @@ -72,6 +72,7 @@ static HandlerResult DisplayOptionsPanel_eventHandler(Panel* super, int ch) { if (result == HANDLED) { this->settings->changed = true; + this->settings->lastUpdate++; Header* header = this->scr->header; Header_calculateHeight(header); Header_reinit(header); diff --git a/HeaderOptionsPanel.c b/HeaderOptionsPanel.c index 22bcd09c1..25d1ddbb7 100644 --- a/HeaderOptionsPanel.c +++ b/HeaderOptionsPanel.c @@ -52,6 +52,7 @@ static HandlerResult HeaderOptionsPanel_eventHandler(Panel* super, int ch) { Header_setLayout(this->scr->header, mark); this->settings->changed = true; + this->settings->lastUpdate++; ScreenManager_resize(this->scr); diff --git a/MetersPanel.c b/MetersPanel.c index 1bdefdb3c..97da63093 100644 --- a/MetersPanel.c +++ b/MetersPanel.c @@ -184,6 +184,7 @@ static HandlerResult MetersPanel_eventHandler(Panel* super, int ch) { if (result == HANDLED || sideMove) { Header* header = this->scr->header; this->settings->changed = true; + this->settings->lastUpdate++; Header_calculateHeight(header); ScreenManager_resize(this->scr); } diff --git a/Process.c b/Process.c index 9d897604f..2a4c809d2 100644 --- a/Process.c +++ b/Process.c @@ -414,6 +414,8 @@ void Process_makeCommandStr(Process* this) { bool stripExeFromCmdline = settings->stripExeFromCmdline; bool showThreadNames = settings->showThreadNames; + uint64_t settingsStamp = settings->lastUpdate; + /* Nothing to do to (Re)Generate the Command string, if the process is: * - a kernel thread, or * - a zombie from before being under htop's watch, or @@ -422,52 +424,27 @@ void Process_makeCommandStr(Process* this) { return; if (this->state == ZOMBIE && !this->mergedCommand.str) return; - if (Process_isUserlandThread(this) && settings->showThreadNames && (showThreadNames == mc->prevShowThreadNames) && (mc->prevMergeSet == showMergedCommand)) - return; /* this->mergedCommand.str needs updating only if its state or contents changed. * Its content is based on the fields cmdline, comm, and exe. */ - if ( - mc->prevMergeSet == showMergedCommand && - mc->prevPathSet == showProgramPath && - mc->prevCommSet == searchCommInCmdline && - mc->prevCmdlineSet == stripExeFromCmdline && - mc->prevShowThreadNames == showThreadNames && - !mc->cmdlineChanged && - !mc->commChanged && - !mc->exeChanged - ) { + if (mc->lastUpdate >= settingsStamp) return; - } + + mc->lastUpdate = settingsStamp; /* The field separtor "│" has been chosen such that it will not match any * valid string used for searching or filtering */ const char* SEPARATOR = CRT_treeStr[TREE_STR_VERT]; const int SEPARATOR_LEN = strlen(SEPARATOR); - /* Check for any changed fields since we last built this string */ - if (mc->cmdlineChanged || mc->commChanged || mc->exeChanged) { - free(mc->str); - /* Accommodate the column text, two field separators and terminating NUL */ - size_t maxLen = 2 * SEPARATOR_LEN + 1; - maxLen += this->cmdline ? strlen(this->cmdline) : strlen("(zombie)"); - maxLen += this->procComm ? strlen(this->procComm) : 0; - maxLen += this->procExe ? strlen(this->procExe) : 0; - - mc->str = xCalloc(1, maxLen); - } - - /* Preserve the settings used in this run */ - mc->prevMergeSet = showMergedCommand; - mc->prevPathSet = showProgramPath; - mc->prevCommSet = searchCommInCmdline; - mc->prevCmdlineSet = stripExeFromCmdline; - mc->prevShowThreadNames = showThreadNames; + /* Accommodate the column text, two field separators and terminating NUL */ + size_t maxLen = 2 * SEPARATOR_LEN + 1; + maxLen += this->cmdline ? strlen(this->cmdline) : strlen("(zombie)"); + maxLen += this->procComm ? strlen(this->procComm) : 0; + maxLen += this->procExe ? strlen(this->procExe) : 0; - /* Mark everything as unchanged */ - mc->cmdlineChanged = false; - mc->commChanged = false; - mc->exeChanged = false; + free(mc->str); + mc->str = xCalloc(1, maxLen); /* Reset all locations that need extra handling when actually displaying */ mc->highlightCount = 0; @@ -1204,7 +1181,8 @@ void Process_updateComm(Process* this, const char* comm) { free(this->procComm); this->procComm = comm ? xStrdup(comm) : NULL; - this->mergedCommand.commChanged = true; + + this->mergedCommand.lastUpdate = 0; } static int skipPotentialPath(const char* cmdline, int end) { @@ -1244,7 +1222,8 @@ void Process_updateCmdline(Process* this, const char* cmdline, int basenameStart this->cmdline = cmdline ? xStrdup(cmdline) : NULL; this->cmdlineBasenameStart = (basenameStart || !cmdline) ? basenameStart : skipPotentialPath(cmdline, basenameEnd); this->cmdlineBasenameEnd = basenameEnd; - this->mergedCommand.cmdlineChanged = true; + + this->mergedCommand.lastUpdate = 0; } void Process_updateExe(Process* this, const char* exe) { @@ -1263,7 +1242,8 @@ void Process_updateExe(Process* this, const char* exe) { this->procExe = NULL; this->procExeBasenameOffset = 0; } - this->mergedCommand.exeChanged = true; + + this->mergedCommand.lastUpdate = 0; } uint8_t Process_fieldWidths[LAST_PROCESSFIELD] = { 0 }; diff --git a/Process.h b/Process.h index a2fa5569a..a1ca50fb5 100644 --- a/Process.h +++ b/Process.h @@ -96,17 +96,10 @@ typedef struct ProcessCmdlineHighlight_ { * Process_writeCommand to color the string. str will be NULL for kernel * threads and zombies */ typedef struct ProcessMergedCommand_ { + uint64_t lastUpdate; /* Marker based on settings->lastUpdate to track when the rendering needs refreshing */ char* str; /* merged Command string */ size_t highlightCount; /* how many portions of cmdline to highlight */ ProcessCmdlineHighlight highlights[8]; /* which portions of cmdline to highlight */ - bool cmdlineChanged : 1; /* whether cmdline changed */ - bool exeChanged : 1; /* whether exe changed */ - bool commChanged : 1; /* whether comm changed */ - bool prevMergeSet : 1; /* whether showMergedCommand was set */ - bool prevPathSet : 1; /* whether showProgramPath was set */ - bool prevCommSet : 1; /* whether findCommInCmdline was set */ - bool prevCmdlineSet : 1; /* whether stripExeFromCmdline was set */ - bool prevShowThreadNames : 1; /* whether showThreadNames was set */ } ProcessMergedCommand; typedef struct Process_ { diff --git a/ScreensPanel.c b/ScreensPanel.c index 1427fef3b..785c3878d 100644 --- a/ScreensPanel.c +++ b/ScreensPanel.c @@ -315,6 +315,7 @@ void ScreensPanel_update(Panel* super) { ScreensPanel* this = (ScreensPanel*) super; int size = Panel_size(super); this->settings->changed = true; + this->settings->lastUpdate++; this->settings->screens = xReallocArray(this->settings->screens, size + 1, sizeof(ScreenSettings*)); for (int i = 0; i < size; i++) { ScreenListItem* item = (ScreenListItem*) Panel_get(super, i); diff --git a/Settings.c b/Settings.c index a6303741a..7d6fca47c 100644 --- a/Settings.c +++ b/Settings.c @@ -762,6 +762,8 @@ Settings* Settings_new(unsigned int initialCpuCount, Hashtable* dynamicColumns) this->ssIndex = 0; this->ss = this->screens[this->ssIndex]; + this->lastUpdate = 1; + return this; } diff --git a/Settings.h b/Settings.h index 345a535cf..facd3f2a2 100644 --- a/Settings.h +++ b/Settings.h @@ -96,6 +96,7 @@ typedef struct Settings_ { #endif bool changed; + uint64_t lastUpdate; } Settings; #define Settings_cpuId(settings, cpu) ((settings)->countCPUsFromOne ? (cpu)+1 : (cpu)) diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c index e799661a0..45b045c87 100644 --- a/linux/LinuxProcessList.c +++ b/linux/LinuxProcessList.c @@ -1351,7 +1351,8 @@ static bool LinuxProcessList_readCmdlineFile(Process* process, openat_arg_t proc if (process->procExeDeleted) filename[filenameLen - markerLen] = '\0'; - process->mergedCommand.exeChanged |= oldExeDeleted ^ process->procExeDeleted; + if (oldExeDeleted != process->procExeDeleted) + process->mergedCommand.lastUpdate = 0; } Process_updateExe(process, filename); @@ -1557,7 +1558,8 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_ lp->m_lrs = (proc->isUserlandThread && parent) ? ((const LinuxProcess*)parent)->m_lrs : 0; } - proc->mergedCommand.exeChanged |= prev ^ proc->usesDeletedLib; + if (prev != proc->usesDeletedLib) + proc->mergedCommand.lastUpdate = 0; } if ((ss->flags & PROCESS_FLAG_LINUX_SMAPS) && !Process_isKernelThread(proc)) {