From 361877454fe56c95a995d5bdbb7eb70c21e39d62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Thu, 15 Oct 2020 22:37:02 +0200 Subject: [PATCH] Cache PAGE_SIZE man:sysconf(3) states: The values obtained from these functions are system configuration constants. They do not change during the lifetime of a process. --- CRT.c | 7 +++++++ CRT.h | 3 +++ Process.c | 4 ++-- Process.h | 7 ------- darwin/DarwinProcess.c | 6 ++++-- dragonflybsd/DragonFlyBSDProcessList.c | 12 +++++++----- freebsd/FreeBSDProcessList.c | 9 +++++---- linux/LinuxProcess.c | 10 +++++----- linux/LinuxProcessList.c | 8 ++++---- openbsd/OpenBSDProcessList.c | 18 +++++++++--------- solaris/SolarisProcessList.c | 25 ++++++++++++++----------- 11 files changed, 60 insertions(+), 49 deletions(-) diff --git a/CRT.c b/CRT.c index d3afd0ec..f6321f4c 100644 --- a/CRT.c +++ b/CRT.c @@ -544,6 +544,9 @@ const char* CRT_termType; int CRT_colorScheme = 0; +long CRT_pageSize = -1; +long CRT_pageSizeKB = -1; + ATTR_NORETURN static void CRT_handleSIGTERM(int sgn) { (void) sgn; @@ -675,6 +678,10 @@ void CRT_init(int delay, int colorScheme, bool allowUnicode) { mousemask(BUTTON1_RELEASED, NULL); #endif + CRT_pageSize = sysconf(_SC_PAGESIZE); + if (CRT_pageSize == -1) + CRT_fatalError("Fatal error: Can not get PAGE_SIZE by sysconf(_SC_PAGESIZE)"); + CRT_pageSizeKB = CRT_pageSize / 1024; } void CRT_done() { diff --git a/CRT.h b/CRT.h index 83cb34e6..606492a4 100644 --- a/CRT.h +++ b/CRT.h @@ -149,6 +149,9 @@ extern const char* CRT_termType; extern int CRT_colorScheme; +extern long CRT_pageSize; +extern long CRT_pageSizeKB; + #ifdef HAVE_SETUID_ENABLED void CRT_dropPrivileges(void); diff --git a/Process.c b/Process.c index 6d9101a7..5f5be13a 100644 --- a/Process.c +++ b/Process.c @@ -311,8 +311,8 @@ void Process_writeField(const Process* this, RichString* str, ProcessField field } case MAJFLT: Process_colorNumber(str, this->majflt, coloring); return; case MINFLT: Process_colorNumber(str, this->minflt, coloring); return; - case M_RESIDENT: Process_humanNumber(str, this->m_resident * PAGE_SIZE_KB, coloring); return; - case M_SIZE: Process_humanNumber(str, this->m_size * PAGE_SIZE_KB, coloring); return; + case M_RESIDENT: Process_humanNumber(str, this->m_resident * CRT_pageSizeKB, coloring); return; + case M_SIZE: Process_humanNumber(str, this->m_size * CRT_pageSizeKB, coloring); return; case NICE: { xSnprintf(buffer, n, "%3ld ", this->nice); attr = this->nice < 0 ? CRT_colors[PROCESS_HIGH_PRIORITY] diff --git a/Process.h b/Process.h index 190a98af..db85f147 100644 --- a/Process.h +++ b/Process.h @@ -21,13 +21,6 @@ in the source distribution for its full text. #define SYS_ioprio_set __NR_ioprio_set #endif -// On Linux, this works only with glibc 2.1+. On earlier versions -// the behavior is similar to have a hardcoded page size. -#ifndef PAGE_SIZE -#define PAGE_SIZE ( sysconf(_SC_PAGESIZE) ) -#endif -#define PAGE_SIZE_KB ( PAGE_SIZE / ONE_K ) - #define PROCESS_FLAG_IO 0x0001 typedef enum ProcessFields { diff --git a/darwin/DarwinProcess.c b/darwin/DarwinProcess.c index 48574e2f..7049cb1e 100644 --- a/darwin/DarwinProcess.c +++ b/darwin/DarwinProcess.c @@ -15,6 +15,8 @@ in the source distribution for its full text. #include +#include "CRT.h" + const ProcessClass DarwinProcess_class = { .super = { @@ -257,8 +259,8 @@ void DarwinProcess_setFromLibprocPidinfo(DarwinProcess *proc, DarwinProcessList proc->super.time = (pti.pti_total_system + pti.pti_total_user) / 10000000; proc->super.nlwp = pti.pti_threadnum; - proc->super.m_size = pti.pti_virtual_size / 1024 / PAGE_SIZE_KB; - proc->super.m_resident = pti.pti_resident_size / 1024 / PAGE_SIZE_KB; + proc->super.m_size = pti.pti_virtual_size / CRT_pageSize; + proc->super.m_resident = pti.pti_resident_size / CRT_pageSize; proc->super.majflt = pti.pti_faults; proc->super.percent_mem = (double)pti.pti_resident_size * 100.0 / (double)dpl->host_info.max_mem; diff --git a/dragonflybsd/DragonFlyBSDProcessList.c b/dragonflybsd/DragonFlyBSDProcessList.c index 87f16069..0792c75b 100644 --- a/dragonflybsd/DragonFlyBSDProcessList.c +++ b/dragonflybsd/DragonFlyBSDProcessList.c @@ -9,7 +9,6 @@ in the source distribution for its full text. #include "ProcessList.h" #include "DragonFlyBSDProcessList.h" #include "DragonFlyBSDProcess.h" -#include "Macros.h" #include #include @@ -22,6 +21,9 @@ in the source distribution for its full text. #include #include +#include "CRT.h" +#include "Macros.h" + static int MIB_hw_physmem[2]; static int MIB_vm_stats_vm_v_page_count[4]; @@ -54,8 +56,8 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui len = sizeof(pageSize); if (sysctlbyname("vm.stats.vm.v_page_size", &pageSize, &len, NULL, 0) == -1) { - pageSize = PAGE_SIZE; - pageSizeKb = PAGE_SIZE_KB; + pageSize = CRT_pageSize; + pageSizeKb = CRT_pageSizeKB; } else { pageSizeKb = pageSize / ONE_K; } @@ -431,12 +433,12 @@ void ProcessList_goThroughEntries(ProcessList* this) { proc->m_size = kproc->kp_vm_map_size / 1024 / pageSizeKb; proc->m_resident = kproc->kp_vm_rssize; - proc->percent_mem = (proc->m_resident * PAGE_SIZE_KB) / (double)(this->totalMem) * 100.0; + proc->percent_mem = (proc->m_resident * CRT_pageSizeKB) / (double)(this->totalMem) * 100.0; proc->nlwp = kproc->kp_nthreads; // number of lwp thread proc->time = (kproc->kp_swtime + 5000) / 10000; proc->percent_cpu = 100.0 * ((double)kproc->kp_lwp.kl_pctcpu / (double)kernelFScale); - proc->percent_mem = 100.0 * (proc->m_resident * PAGE_SIZE_KB) / (double)(this->totalMem); + proc->percent_mem = 100.0 * (proc->m_resident * pageSizeKb) / (double)(this->totalMem); if (proc->percent_cpu > 0.1) { // system idle process should own all CPU time left regardless of CPU count diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c index 62969876..b13b217b 100644 --- a/freebsd/FreeBSDProcessList.c +++ b/freebsd/FreeBSDProcessList.c @@ -19,6 +19,7 @@ in the source distribution for its full text. #include #include +#include "CRT.h" #include "FreeBSDProcess.h" #include "Macros.h" #include "ProcessList.h" @@ -60,8 +61,8 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui len = sizeof(pageSize); if (sysctlbyname("vm.stats.vm.v_page_size", &pageSize, &len, NULL, 0) == -1) { - pageSize = PAGE_SIZE; - pageSizeKb = PAGE_SIZE_KB; + pageSize = CRT_pageSize; + pageSizeKb = CRT_pageSize; } else { pageSizeKb = pageSize / ONE_K; } @@ -446,12 +447,12 @@ void ProcessList_goThroughEntries(ProcessList* this) { // from FreeBSD source /src/usr.bin/top/machine.c proc->m_size = kproc->ki_size / 1024 / pageSizeKb; proc->m_resident = kproc->ki_rssize; - proc->percent_mem = (proc->m_resident * PAGE_SIZE_KB) / (double)(this->totalMem) * 100.0; + proc->percent_mem = (proc->m_resident * pageSizeKb) / (double)(this->totalMem) * 100.0; proc->nlwp = kproc->ki_numthreads; proc->time = (kproc->ki_runtime + 5000) / 10000; proc->percent_cpu = 100.0 * ((double)kproc->ki_pctcpu / (double)kernelFScale); - proc->percent_mem = 100.0 * (proc->m_resident * PAGE_SIZE_KB) / (double)(this->totalMem); + proc->percent_mem = 100.0 * (proc->m_resident * pageSizeKb) / (double)(this->totalMem); /* * TODO diff --git a/linux/LinuxProcess.c b/linux/LinuxProcess.c index 6d1e3ca6..8003157c 100644 --- a/linux/LinuxProcess.c +++ b/linux/LinuxProcess.c @@ -215,11 +215,11 @@ void LinuxProcess_writeField(Process* this, RichString* str, ProcessField field) } case CMINFLT: Process_colorNumber(str, lp->cminflt, coloring); return; case CMAJFLT: Process_colorNumber(str, lp->cmajflt, coloring); return; - case M_DRS: Process_humanNumber(str, lp->m_drs * PAGE_SIZE_KB, coloring); return; - case M_DT: Process_humanNumber(str, lp->m_dt * PAGE_SIZE_KB, coloring); return; - case M_LRS: Process_humanNumber(str, lp->m_lrs * PAGE_SIZE_KB, coloring); return; - case M_TRS: Process_humanNumber(str, lp->m_trs * PAGE_SIZE_KB, coloring); return; - case M_SHARE: Process_humanNumber(str, lp->m_share * PAGE_SIZE_KB, coloring); return; + case M_DRS: Process_humanNumber(str, lp->m_drs * CRT_pageSizeKB, coloring); return; + case M_DT: Process_humanNumber(str, lp->m_dt * CRT_pageSizeKB, coloring); return; + case M_LRS: Process_humanNumber(str, lp->m_lrs * CRT_pageSizeKB, coloring); return; + case M_TRS: Process_humanNumber(str, lp->m_trs * CRT_pageSizeKB, coloring); return; + case M_SHARE: Process_humanNumber(str, lp->m_share * CRT_pageSizeKB, coloring); return; case M_PSS: Process_humanNumber(str, lp->m_pss, coloring); return; case M_SWAP: Process_humanNumber(str, lp->m_swap, coloring); return; case M_PSSWP: Process_humanNumber(str, lp->m_psswp, coloring); return; diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c index 1ed13826..2739c790 100644 --- a/linux/LinuxProcessList.c +++ b/linux/LinuxProcessList.c @@ -479,14 +479,14 @@ static bool LinuxProcessList_readSmapsFile(LinuxProcess* process, const char* di //http://elixir.free-electrons.com/linux/v4.10/source/fs/proc/task_mmu.c#L719 //kernel will return data in chunks of size PAGE_SIZE or less. - char buffer[PAGE_SIZE];// 4k + char buffer[CRT_pageSize];// 4k char *start,*end; ssize_t nread=0; int tmp=0; if(haveSmapsRollup) {// only available in Linux 4.14+ - snprintf(buffer, PAGE_SIZE-1, "%s/%s/smaps_rollup", dirname, name); + xSnprintf(buffer, sizeof(buffer), "%s/%s/smaps_rollup", dirname, name); } else { - snprintf(buffer, PAGE_SIZE-1, "%s/%s/smaps", dirname, name); + xSnprintf(buffer, sizeof(buffer), "%s/%s/smaps", dirname, name); } int fd = open(buffer, O_RDONLY); if (fd == -1) @@ -1020,7 +1020,7 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, const char* float percent_cpu = (lp->utime + lp->stime - lasttimes) / period * 100.0; proc->percent_cpu = CLAMP(percent_cpu, 0.0, cpus * 100.0); if (isnan(proc->percent_cpu)) proc->percent_cpu = 0.0; - proc->percent_mem = (proc->m_resident * PAGE_SIZE_KB) / (double)(pl->totalMem) * 100.0; + proc->percent_mem = (proc->m_resident * CRT_pageSizeKB) / (double)(pl->totalMem) * 100.0; if(!preExisting) { diff --git a/openbsd/OpenBSDProcessList.c b/openbsd/OpenBSDProcessList.c index 4b030707..744b8a98 100644 --- a/openbsd/OpenBSDProcessList.c +++ b/openbsd/OpenBSDProcessList.c @@ -91,7 +91,7 @@ static inline void OpenBSDProcessList_scanMemoryInfo(ProcessList* pl) { err(1, "uvmexp sysctl call failed"); } - pl->totalMem = uvmexp.npages * PAGE_SIZE_KB; + pl->totalMem = uvmexp.npages * CRT_pageSizeKB; // Taken from OpenBSD systat/iostat.c, top/machine.c and uvm_sysctl(9) static int bcache_mib[] = {CTL_VFS, VFS_GENERIC, VFS_BCACHESTAT}; @@ -102,9 +102,9 @@ static inline void OpenBSDProcessList_scanMemoryInfo(ProcessList* pl) { err(1, "cannot get vfs.bcachestat"); } - pl->cachedMem = bcstats.numbufpages * PAGE_SIZE_KB; - pl->freeMem = uvmexp.free * PAGE_SIZE_KB; - pl->usedMem = (uvmexp.npages - uvmexp.free - uvmexp.paging) * PAGE_SIZE_KB; + pl->cachedMem = bcstats.numbufpages * CRT_pageSizeKB; + pl->freeMem = uvmexp.free * CRT_pageSizeKB; + pl->usedMem = (uvmexp.npages - uvmexp.free - uvmexp.paging) * CRT_pageSizeKB; /* const OpenBSDProcessList* opl = (OpenBSDProcessList*) pl; @@ -113,10 +113,10 @@ static inline void OpenBSDProcessList_scanMemoryInfo(ProcessList* pl) { sysctl(MIB_hw_physmem, 2, &(pl->totalMem), &len, NULL, 0); pl->totalMem /= 1024; sysctl(MIB_vm_stats_vm_v_wire_count, 4, &(pl->usedMem), &len, NULL, 0); - pl->usedMem *= PAGE_SIZE_KB; + pl->usedMem *= CRT_pageSizeKB; pl->freeMem = pl->totalMem - pl->usedMem; sysctl(MIB_vm_stats_vm_v_cache_count, 4, &(pl->cachedMem), &len, NULL, 0); - pl->cachedMem *= PAGE_SIZE_KB; + pl->cachedMem *= CRT_pageSizeKB; struct kvm_swap swap[16]; int nswap = kvm_getswapinfo(opl->kd, swap, ARRAYSIZE(swap), 0); @@ -126,8 +126,8 @@ static inline void OpenBSDProcessList_scanMemoryInfo(ProcessList* pl) { pl->totalSwap += swap[i].ksw_total; pl->usedSwap += swap[i].ksw_used; } - pl->totalSwap *= PAGE_SIZE_KB; - pl->usedSwap *= PAGE_SIZE_KB; + pl->totalSwap *= CRT_pageSizeKB; + pl->usedSwap *= CRT_pageSizeKB; pl->sharedMem = 0; // currently unused pl->buffersMem = 0; // not exposed to userspace @@ -231,7 +231,7 @@ static inline void OpenBSDProcessList_scanProcs(OpenBSDProcessList* this) { proc->m_size = kproc->p_vm_dsize; proc->m_resident = kproc->p_vm_rssize; - proc->percent_mem = (proc->m_resident * PAGE_SIZE_KB) / (double)(this->super.totalMem) * 100.0; + proc->percent_mem = (proc->m_resident * CRT_pageSizeKB) / (double)(this->super.totalMem) * 100.0; proc->percent_cpu = CLAMP(getpcpu(kproc), 0.0, this->super.cpuCount*100.0); //proc->nlwp = kproc->p_numthreads; //proc->time = kproc->p_rtime_sec + ((kproc->p_rtime_usec + 500000) / 10); diff --git a/solaris/SolarisProcessList.c b/solaris/SolarisProcessList.c index 9662f830..ea552841 100644 --- a/solaris/SolarisProcessList.c +++ b/solaris/SolarisProcessList.c @@ -23,6 +23,9 @@ in the source distribution for its full text. #include #include +#include "CRT.h" + + #define MAXCMDLINE 255 char* SolarisProcessList_readZoneName(kstat_ctl_t* kd, SolarisProcess* sproc) { @@ -157,22 +160,22 @@ static inline void SolarisProcessList_scanMemoryInfo(ProcessList* pl) { freemem_pgs = kstat_data_lookup(meminfo, "freemem"); pages = kstat_data_lookup(meminfo, "pagestotal"); - pl->totalMem = totalmem_pgs->value.ui64 * PAGE_SIZE_KB; - if (pl->totalMem > freemem_pgs->value.ui64 * PAGE_SIZE_KB) - pl->usedMem = pl->totalMem - freemem_pgs->value.ui64 * PAGE_SIZE_KB; + pl->totalMem = totalmem_pgs->value.ui64 * CRT_pageSizeKB; + if (pl->totalMem > freemem_pgs->value.ui64 * CRT_pageSizeKB) + pl->usedMem = pl->totalMem - freemem_pgs->value.ui64 * CRT_pageSizeKB; else - pl->usedMem = 0; // This can happen in non-global zone (in theory) + pl->usedMem = 0; // This can happen in non-global zone (in theory) // Not sure how to implement this on Solaris - suggestions welcome! pl->cachedMem = 0; // Not really "buffers" but the best Solaris analogue that I can find to // "memory in use but not by programs or the kernel itself" - pl->buffersMem = (totalmem_pgs->value.ui64 - pages->value.ui64) * PAGE_SIZE_KB; + pl->buffersMem = (totalmem_pgs->value.ui64 - pages->value.ui64) * CRT_pageSizeKB; } else { // Fall back to basic sysconf if kstat isn't working - pl->totalMem = sysconf(_SC_PHYS_PAGES) * PAGE_SIZE; + pl->totalMem = sysconf(_SC_PHYS_PAGES) * CRT_pageSize; pl->buffersMem = 0; pl->cachedMem = 0; - pl->usedMem = pl->totalMem - (sysconf(_SC_AVPHYS_PAGES) * PAGE_SIZE); + pl->usedMem = pl->totalMem - (sysconf(_SC_AVPHYS_PAGES) * CRT_pageSize); } // Part 2 - swap @@ -198,8 +201,8 @@ static inline void SolarisProcessList_scanMemoryInfo(ProcessList* pl) { } free(spathbase); free(sl); - pl->totalSwap = totalswap * PAGE_SIZE_KB; - pl->usedSwap = pl->totalSwap - (totalfree * PAGE_SIZE_KB); + pl->totalSwap = totalswap * CRT_pageSizeKB; + pl->usedSwap = pl->totalSwap - (totalfree * CRT_pageSizeKB); } static inline void SolarisProcessList_scanZfsArcstats(ProcessList* pl) { @@ -297,8 +300,8 @@ int SolarisProcessList_walkproc(psinfo_t *_psinfo, lwpsinfo_t *_lwpsinfo, void * proc->pgrp = _psinfo->pr_pgid; proc->nlwp = _psinfo->pr_nlwp; proc->tty_nr = _psinfo->pr_ttydev; - proc->m_resident = _psinfo->pr_rssize/PAGE_SIZE_KB; - proc->m_size = _psinfo->pr_size/PAGE_SIZE_KB; + proc->m_resident = _psinfo->pr_rssize/CRT_pageSizeKB; + proc->m_size = _psinfo->pr_size/CRT_pageSizeKB; if (!preExisting) { sproc->realpid = _psinfo->pr_pid;