diff --git a/Process.c b/Process.c index 9f33a57e..876b3b72 100644 --- a/Process.c +++ b/Process.c @@ -49,8 +49,8 @@ void Process_setupColumnWidths() { assert(Process_pidDigits <= PROCESS_MAX_PID_DIGITS); } -void Process_humanNumber(RichString* str, unsigned long long number, bool coloring) { - char buffer[10]; +void Process_printBytes(RichString* str, unsigned long long number, bool coloring) { + char buffer[16]; int len; int largeNumberColor = coloring ? CRT_colors[LARGE_NUMBER] : CRT_colors[PROCESS]; @@ -62,7 +62,12 @@ void Process_humanNumber(RichString* str, unsigned long long number, bool colori if (number == ULLONG_MAX) { //Invalid number RichString_appendAscii(str, shadowColor, " N/A "); - } else if (number < 1000) { + return; + } + + number /= ONE_K; + + if (number < 1000) { //Plain number, no markings len = xSnprintf(buffer, sizeof(buffer), "%5llu ", number); RichString_appendnAscii(str, processColor, buffer, len); @@ -108,14 +113,35 @@ void Process_humanNumber(RichString* str, unsigned long long number, bool colori number %= 1000; len = xSnprintf(buffer, sizeof(buffer), "%03lluG ", number); RichString_appendnAscii(str, processGigabytesColor, buffer, len); + } else if (number < 100000 * ONE_M) { + //2 digit TB, 1 digit GB + number /= 100 * ONE_M; + len = xSnprintf(buffer, sizeof(buffer), "%2llu", number/10); + RichString_appendnAscii(str, largeNumberColor, buffer, len); + number %= 10; + len = xSnprintf(buffer, sizeof(buffer), ".%1llu", number); + RichString_appendnAscii(str, processGigabytesColor, buffer, len); + RichString_appendAscii(str, largeNumberColor, "T "); + } else if (number < 10000ULL * ONE_G) { + //3 digit TB or 1 digit PB, 3 digit TB + number /= ONE_G; + len = xSnprintf(buffer, sizeof(buffer), "%4lluT ", number); + RichString_appendnAscii(str, largeNumberColor, buffer, len); } else { - //2 digit TB and above - len = xSnprintf(buffer, sizeof(buffer), "%4.1lfT ", (double)number/ONE_G); + //2 digit PB and above + len = xSnprintf(buffer, sizeof(buffer), "%4.1lfP ", (double)number/ONE_T); RichString_appendnAscii(str, largeNumberColor, buffer, len); } } -void Process_colorNumber(RichString* str, unsigned long long number, bool coloring) { +void Process_printKBytes(RichString* str, unsigned long long number, bool coloring) { + if (number == ULLONG_MAX) + Process_printBytes(str, ULLONG_MAX, coloring); + else + Process_printBytes(str, number * ONE_K, coloring); +} + +void Process_printCount(RichString* str, unsigned long long number, bool coloring) { char buffer[13]; int largeNumberColor = coloring ? CRT_colors[LARGE_NUMBER] : CRT_colors[PROCESS]; @@ -146,30 +172,78 @@ void Process_colorNumber(RichString* str, unsigned long long number, bool colori } } -void Process_printTime(RichString* str, unsigned long long totalHundredths) { - unsigned long long totalSeconds = totalHundredths / 100; +void Process_printTime(RichString* str, unsigned long long totalHundredths, bool coloring) { + char buffer[10]; + int len; + unsigned long long totalSeconds = totalHundredths / 100; unsigned long long hours = totalSeconds / 3600; unsigned long long days = totalSeconds / 86400; int minutes = (totalSeconds / 60) % 60; int seconds = totalSeconds % 60; int hundredths = totalHundredths - (totalSeconds * 100); - char buffer[10]; - if (days >= 100) { - xSnprintf(buffer, sizeof(buffer), "%7llud ", days); - RichString_appendAscii(str, CRT_colors[LARGE_NUMBER], buffer); - } else if (hours >= 100) { - xSnprintf(buffer, sizeof(buffer), "%7lluh ", hours); - RichString_appendAscii(str, CRT_colors[LARGE_NUMBER], buffer); - } else { - if (hours) { - xSnprintf(buffer, sizeof(buffer), "%2lluh", hours); - RichString_appendAscii(str, CRT_colors[LARGE_NUMBER], buffer); - xSnprintf(buffer, sizeof(buffer), "%02d:%02d ", minutes, seconds); + + int yearColor = coloring ? CRT_colors[LARGE_NUMBER] : CRT_colors[PROCESS]; + int dayColor = coloring ? CRT_colors[PROCESS_GIGABYTES] : CRT_colors[PROCESS]; + int hourColor = coloring ? CRT_colors[PROCESS_MEGABYTES] : CRT_colors[PROCESS]; + int defColor = CRT_colors[PROCESS]; + + if (days >= /* Ignore leapyears */365) { + int years = days / 365; + int daysLeft = days - 365 * years; + + if (daysLeft >= 100) { + len = xSnprintf(buffer, sizeof(buffer), "%3dy", years); + RichString_appendnAscii(str, yearColor, buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%3dd ", daysLeft); + RichString_appendnAscii(str, dayColor, buffer, len); + } else if (daysLeft >= 10) { + len = xSnprintf(buffer, sizeof(buffer), "%4dy", years); + RichString_appendnAscii(str, yearColor, buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%2dd ", daysLeft); + RichString_appendnAscii(str, dayColor, buffer, len); } else { - xSnprintf(buffer, sizeof(buffer), "%2d:%02d.%02d ", minutes, seconds, hundredths); + len = xSnprintf(buffer, sizeof(buffer), "%5dy", years); + RichString_appendnAscii(str, yearColor, buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%1dd ", daysLeft); + RichString_appendnAscii(str, dayColor, buffer, len); } - RichString_appendAscii(str, CRT_colors[DEFAULT_COLOR], buffer); + } else if (days >= 100) { + int hoursLeft = hours - days * 24; + + if (hoursLeft >= 10) { + len = xSnprintf(buffer, sizeof(buffer), "%4llud", days); + RichString_appendnAscii(str, dayColor, buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%2dh ", hoursLeft); + RichString_appendnAscii(str, hourColor, buffer, len); + } else { + len = xSnprintf(buffer, sizeof(buffer), "%5llud", days); + RichString_appendnAscii(str, dayColor, buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%1dh ", hoursLeft); + RichString_appendnAscii(str, hourColor, buffer, len); + } + } else if (hours >= 100) { + int minutesLeft = totalSeconds / 60 - hours * 60; + + if (minutesLeft >= 10) { + len = xSnprintf(buffer, sizeof(buffer), "%4lluh", hours); + RichString_appendnAscii(str, hourColor, buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%2dm ", minutesLeft); + RichString_appendnAscii(str, defColor, buffer, len); + } else { + len = xSnprintf(buffer, sizeof(buffer), "%5lluh", hours); + RichString_appendnAscii(str, hourColor, buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%1dm ", minutesLeft); + RichString_appendnAscii(str, defColor, buffer, len); + } + } else if (hours > 0) { + len = xSnprintf(buffer, sizeof(buffer), "%2lluh", hours); + RichString_appendnAscii(str, hourColor, buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%02d:%02d ", minutes, seconds); + RichString_appendnAscii(str, defColor, buffer, len); + } else { + len = xSnprintf(buffer, sizeof(buffer), "%2d:%02d.%02d ", minutes, seconds, hundredths); + RichString_appendnAscii(str, defColor, buffer, len); } } @@ -211,10 +285,13 @@ static inline void Process_writeCommand(const Process* this, int attr, int basea } } -void Process_outputRate(RichString* str, char* buffer, size_t n, double rate, int coloring) { +void Process_printRate(RichString* str, double rate, bool coloring) { + char buffer[16]; + int largeNumberColor = CRT_colors[LARGE_NUMBER]; int processMegabytesColor = CRT_colors[PROCESS_MEGABYTES]; int processColor = CRT_colors[PROCESS]; + int shadowColor = CRT_colors[PROCESS_SHADOW]; if (!coloring) { largeNumberColor = CRT_colors[PROCESS]; @@ -222,21 +299,27 @@ void Process_outputRate(RichString* str, char* buffer, size_t n, double rate, in } if (isnan(rate)) { - RichString_appendAscii(str, CRT_colors[PROCESS_SHADOW], " N/A "); + RichString_appendAscii(str, shadowColor, " N/A "); + } else if (rate < 0.005) { + int len = snprintf(buffer, sizeof(buffer), "%7.2f B/s ", rate); + RichString_appendnAscii(str, shadowColor, buffer, len); } else if (rate < ONE_K) { - int len = snprintf(buffer, n, "%7.2f B/s ", rate); + int len = snprintf(buffer, sizeof(buffer), "%7.2f B/s ", rate); RichString_appendnAscii(str, processColor, buffer, len); } else if (rate < ONE_M) { - int len = snprintf(buffer, n, "%7.2f K/s ", rate / ONE_K); + int len = snprintf(buffer, sizeof(buffer), "%7.2f K/s ", rate / ONE_K); RichString_appendnAscii(str, processColor, buffer, len); } else if (rate < ONE_G) { - int len = snprintf(buffer, n, "%7.2f M/s ", rate / ONE_M); + int len = snprintf(buffer, sizeof(buffer), "%7.2f M/s ", rate / ONE_M); RichString_appendnAscii(str, processMegabytesColor, buffer, len); } else if (rate < ONE_T) { - int len = snprintf(buffer, n, "%7.2f G/s ", rate / ONE_G); + int len = snprintf(buffer, sizeof(buffer), "%7.2f G/s ", rate / ONE_G); + RichString_appendnAscii(str, largeNumberColor, buffer, len); + } else if (rate < ONE_P) { + int len = snprintf(buffer, sizeof(buffer), "%7.2f T/s ", rate / ONE_T); RichString_appendnAscii(str, largeNumberColor, buffer, len); } else { - int len = snprintf(buffer, n, "%7.2f T/s ", rate / ONE_T); + int len = snprintf(buffer, sizeof(buffer), "%7.2f P/s ", rate / ONE_P); RichString_appendnAscii(str, largeNumberColor, buffer, len); } } @@ -298,10 +381,10 @@ void Process_writeField(const Process* this, RichString* str, ProcessField field Process_writeCommand(this, attr, baseattr, str); return; } - 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, coloring); return; - case M_VIRT: Process_humanNumber(str, this->m_virt, coloring); return; + case MAJFLT: Process_printCount(str, this->majflt, coloring); return; + case MINFLT: Process_printCount(str, this->minflt, coloring); return; + case M_RESIDENT: Process_printKBytes(str, this->m_resident, coloring); return; + case M_VIRT: Process_printKBytes(str, this->m_virt, coloring); return; case NICE: xSnprintf(buffer, n, "%3ld ", this->nice); attr = this->nice < 0 ? CRT_colors[PROCESS_HIGH_PRIORITY] @@ -370,7 +453,7 @@ void Process_writeField(const Process* this, RichString* str, ProcessField field } break; case ST_UID: xSnprintf(buffer, n, "%5d ", this->st_uid); break; - case TIME: Process_printTime(str, this->time); return; + case TIME: Process_printTime(str, this->time, coloring); return; case TGID: if (this->tgid == this->pid) attr = CRT_colors[PROCESS_SHADOW]; diff --git a/Process.h b/Process.h index a0bdea74..9887bd13 100644 --- a/Process.h +++ b/Process.h @@ -245,28 +245,33 @@ static inline bool Process_isChildOf(const Process* this, pid_t pid) { #define ONE_M (ONE_K * ONE_K) #define ONE_G (ONE_M * ONE_K) #define ONE_T (1ULL * ONE_G * ONE_K) +#define ONE_P (1ULL * ONE_T * ONE_K) #define ONE_DECIMAL_K 1000UL #define ONE_DECIMAL_M (ONE_DECIMAL_K * ONE_DECIMAL_K) #define ONE_DECIMAL_G (ONE_DECIMAL_M * ONE_DECIMAL_K) #define ONE_DECIMAL_T (1ULL * ONE_DECIMAL_G * ONE_DECIMAL_K) +#define ONE_DECIMAL_P (1ULL * ONE_DECIMAL_T * ONE_DECIMAL_K) void Process_setupColumnWidths(void); -/* Takes number in kilo units (base 1024) */ -void Process_humanNumber(RichString* str, unsigned long long number, bool coloring); +/* Takes number in bytes (base 1024). Prints 6 columns. */ +void Process_printBytes(RichString* str, unsigned long long number, bool coloring); -/* Takes number in bare units (base 1000) */ -void Process_colorNumber(RichString* str, unsigned long long number, bool coloring); +/* Takes number in kilo bytes (base 1024). Prints 6 columns. */ +void Process_printKBytes(RichString* str, unsigned long long number, bool coloring); -/* Takes number in hundredths of a seconds */ -void Process_printTime(RichString* str, unsigned long long totalHundredths); +/* Takes number as count (base 1000). Prints 12 columns. */ +void Process_printCount(RichString* str, unsigned long long number, bool coloring); + +/* Takes time in hundredths of a seconds. Prints 9 columns. */ +void Process_printTime(RichString* str, unsigned long long totalHundredths, bool coloring); + +/* Takes rate in bare unit (base 1024) per second. Prints 12 columns. */ +void Process_printRate(RichString* str, double rate, bool coloring); void Process_fillStarttimeBuffer(Process* this); -/* Takes number in bare units (base 1024) */ -void Process_outputRate(RichString* str, char* buffer, size_t n, double rate, int coloring); - void Process_printLeftAlignedField(RichString* str, int attr, const char* content, unsigned int width); void Process_display(const Object* cast, RichString* out); diff --git a/linux/LinuxProcess.c b/linux/LinuxProcess.c index f511b413..df7df94e 100644 --- a/linux/LinuxProcess.c +++ b/linux/LinuxProcess.c @@ -609,37 +609,37 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces int attr = CRT_colors[DEFAULT_COLOR]; size_t n = sizeof(buffer) - 1; switch (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 * pageSizeKB, coloring); return; - case M_DT: Process_humanNumber(str, lp->m_dt * pageSizeKB, coloring); return; + case CMINFLT: Process_printCount(str, lp->cminflt, coloring); return; + case CMAJFLT: Process_printCount(str, lp->cmajflt, coloring); return; + case M_DRS: Process_printKBytes(str, lp->m_drs * pageSizeKB, coloring); return; + case M_DT: Process_printKBytes(str, lp->m_dt * pageSizeKB, coloring); return; case M_LRS: if (lp->m_lrs) { - Process_humanNumber(str, lp->m_lrs * pageSizeKB, coloring); + Process_printKBytes(str, lp->m_lrs * pageSizeKB, coloring); return; } attr = CRT_colors[PROCESS_SHADOW]; xSnprintf(buffer, n, " N/A "); break; - case M_TRS: Process_humanNumber(str, lp->m_trs * pageSizeKB, coloring); return; - case M_SHARE: Process_humanNumber(str, lp->m_share * 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; - case UTIME: Process_printTime(str, lp->utime); return; - case STIME: Process_printTime(str, lp->stime); return; - case CUTIME: Process_printTime(str, lp->cutime); return; - case CSTIME: Process_printTime(str, lp->cstime); return; - case RCHAR: Process_humanNumber(str, lp->io_rchar, coloring); return; - case WCHAR: Process_humanNumber(str, lp->io_wchar, coloring); return; - case SYSCR: Process_colorNumber(str, lp->io_syscr, coloring); return; - case SYSCW: Process_colorNumber(str, lp->io_syscw, coloring); return; - case RBYTES: Process_humanNumber(str, lp->io_read_bytes, coloring); return; - case WBYTES: Process_humanNumber(str, lp->io_write_bytes, coloring); return; - case CNCLWB: Process_humanNumber(str, lp->io_cancelled_write_bytes, coloring); return; - case IO_READ_RATE: Process_outputRate(str, buffer, n, lp->io_rate_read_bps, coloring); return; - case IO_WRITE_RATE: Process_outputRate(str, buffer, n, lp->io_rate_write_bps, coloring); return; + case M_TRS: Process_printKBytes(str, lp->m_trs * pageSizeKB, coloring); return; + case M_SHARE: Process_printKBytes(str, lp->m_share * pageSizeKB, coloring); return; + case M_PSS: Process_printKBytes(str, lp->m_pss, coloring); return; + case M_SWAP: Process_printKBytes(str, lp->m_swap, coloring); return; + case M_PSSWP: Process_printKBytes(str, lp->m_psswp, coloring); return; + case UTIME: Process_printTime(str, lp->utime, coloring); return; + case STIME: Process_printTime(str, lp->stime, coloring); return; + case CUTIME: Process_printTime(str, lp->cutime, coloring); return; + case CSTIME: Process_printTime(str, lp->cstime, coloring); return; + case RCHAR: Process_printKBytes(str, lp->io_rchar, coloring); return; + case WCHAR: Process_printKBytes(str, lp->io_wchar, coloring); return; + case SYSCR: Process_printCount(str, lp->io_syscr, coloring); return; + case SYSCW: Process_printCount(str, lp->io_syscw, coloring); return; + case RBYTES: Process_printKBytes(str, lp->io_read_bytes, coloring); return; + case WBYTES: Process_printKBytes(str, lp->io_write_bytes, coloring); return; + case CNCLWB: Process_printKBytes(str, lp->io_cancelled_write_bytes, coloring); return; + case IO_READ_RATE: Process_printRate(str, lp->io_rate_read_bps, coloring); return; + case IO_WRITE_RATE: Process_printRate(str, lp->io_rate_write_bps, coloring); return; case IO_RATE: { double totalRate; if (!isnan(lp->io_rate_read_bps) && !isnan(lp->io_rate_write_bps)) @@ -650,7 +650,7 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces totalRate = lp->io_rate_write_bps; else totalRate = NAN; - Process_outputRate(str, buffer, n, totalRate, coloring); return; + Process_printRate(str, totalRate, coloring); return; } #ifdef HAVE_OPENVZ case CTID: xSnprintf(buffer, n, "%-8s ", lp->ctid ? lp->ctid : ""); break;