top: exploit the new library API for memory statistics

This commit represents the pioneering attempt at using
the concept of 'chained' library requests in an effort
to reduce function call overhead. It required exposing
no more implementation details than were already shown
through the individual calls, yet is satisfied in one.

It is just such an approach that will prove invaluable
when it comes time to access individual /proc/##/data.
Programs could 'chain' only those 'results' structures
representing their current view independent of all the
fields any such programs might be prepared to display.

Thus the standard 'read', which wouldn't apply to task
level data very well (or efficiently), can now become
a 'read_chain' whereby the former PROC_FILL flags need
can be satisfied & yield the minimum open/close calls.

Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
Jim Warner 2015-06-28 00:00:00 -05:00 committed by Craig Small
parent a05084f381
commit c3fd7473c5
3 changed files with 52 additions and 26 deletions

View File

@ -50,6 +50,7 @@
#include "../include/nls.h" #include "../include/nls.h"
#include "../proc/devname.h" #include "../proc/devname.h"
#include "../proc/meminfo.h"
#include "../proc/procps.h" #include "../proc/procps.h"
#include "../proc/readproc.h" #include "../proc/readproc.h"
#include "../proc/sig.h" #include "../proc/sig.h"
@ -244,6 +245,26 @@ static float Graph_adj; // bars/blocks scaling factor
static int Graph_len; // scaled length (<= GRAPH_actual) static int Graph_len; // scaled length (<= GRAPH_actual)
static const char Graph_blks[] = " "; static const char Graph_blks[] = " ";
static const char Graph_bars[] = "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"; static const char Graph_bars[] = "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||";
/* Support for the new library API -- acquired (if necessary)
at program startup and referenced throughout our lifetime */
static struct procps_meminfo *mem_info;
static struct meminfo_result mem_chain[] = {
{ PROCPS_MEM_FREE, 0, &mem_chain[1] },
{ PROCPS_MEM_USED, 0, &mem_chain[2] },
{ PROCPS_MEM_TOTAL, 0, &mem_chain[3] },
{ PROCPS_MEM_CACHED, 0, &mem_chain[4] },
{ PROCPS_MEM_BUFFERS, 0, &mem_chain[5] },
{ PROCPS_MEM_AVAILABLE, 0, &mem_chain[6] },
{ PROCPS_SWAP_TOTAL, 0, &mem_chain[7] },
{ PROCPS_SWAP_FREE, 0, &mem_chain[8] },
{ PROCPS_SWAP_USED, 0, NULL }
};
enum mem_enums {
mem_FREE, mem_USED, mem_TOTAL, mem_CACHE, mem_BUFFS,
mem_AVAIL, swp_TOTAL, swp_FREE, swp_USED
};
#define MEM_VAL(e) mem_chain[e].result
/*###### Sort callbacks ################################################*/ /*###### Sort callbacks ################################################*/
@ -2697,7 +2718,9 @@ static void sysinfo_refresh (int forced) {
/*** hotplug_acclimated ***/ /*** hotplug_acclimated ***/
if (3 <= cur_secs - mem_secs) { if (3 <= cur_secs - mem_secs) {
meminfo(); if (procps_meminfo_read(mem_info) < 0)
error_exit(N_txt(LIB_errormem_txt));
procps_meminfo_get_chain(mem_info, mem_chain);
mem_secs = cur_secs; mem_secs = cur_secs;
} }
#ifndef PRETEND8CPUS #ifndef PRETEND8CPUS
@ -3293,6 +3316,10 @@ static void before (char *me) {
i = page_bytes; // from sysinfo.c, at lib init i = page_bytes; // from sysinfo.c, at lib init
while(i > 1024) { i >>= 1; Pg2K_shft++; } while(i > 1024) { i >>= 1; Pg2K_shft++; }
// prepare for new library API ...
if (procps_meminfo_new(&mem_info) < 0)
error_exit(N_txt(LIB_errormem_txt));
#ifndef OFF_HST_HASH #ifndef OFF_HST_HASH
// prep for HST_t's put/get hashing optimizations // prep for HST_t's put/get hashing optimizations
for (i = 0; i < HHASH_SIZ; i++) HHash_nul[i] = -1; for (i = 0; i < HHASH_SIZ; i++) HHash_nul[i] = -1;
@ -5207,8 +5234,7 @@ numa_nope:
if (isROOM(View_MEMORY, 2)) { if (isROOM(View_MEMORY, 2)) {
#define bfT(n) buftab[n].buf #define bfT(n) buftab[n].buf
#define scT(e) scaletab[Rc.summ_mscale]. e #define scT(e) scaletab[Rc.summ_mscale]. e
#define mkM(x) (float)kb_main_ ## x / scT(div) #define mkM(x) (float) x / scT(div)
#define mkS(x) (float)kb_swap_ ## x / scT(div)
#define prT(b,z) { if (9 < snprintf(b, 10, scT(fmts), z)) b[8] = '+'; } #define prT(b,z) { if (9 < snprintf(b, 10, scT(fmts), z)) b[8] = '+'; }
static struct { static struct {
float div; float div;
@ -5246,13 +5272,13 @@ numa_nope:
}; };
char used[SMLBUFSIZ], util[SMLBUFSIZ], dual[MEDBUFSIZ]; char used[SMLBUFSIZ], util[SMLBUFSIZ], dual[MEDBUFSIZ];
int ix = w->rc.graph_mems - 1; int ix = w->rc.graph_mems - 1;
float pct_used = (float)kb_main_used * (100.0 / (float)kb_main_total), float pct_used = (float)MEM_VAL(mem_USED) * (100.0 / (float)MEM_VAL(mem_TOTAL)),
#ifdef MEMGRAPH_OLD #ifdef MEMGRAPH_OLD
pct_misc = (float)(kb_main_buffers + kb_main_cached) * (100.0 / (float)kb_main_total), pct_misc = (float)(MEM_VAL(mem_BUFFS) + MEM_VAL(mem_CACHE)) * (100.0 / (float)MEM_VAL(mem_TOTAL)),
#else #else
pct_misc = (float)(kb_main_total - kb_main_available - kb_main_used) * (100.0 / (float)kb_main_total), pct_misc = (float)(MEM_VAL(mem_TOTAL) - MEM_VAL(mem_AVAIL) - MEM_VAL(mem_USED)) * (100.0 / (float)MEM_VAL(mem_TOTAL)),
#endif #endif
pct_swap = kb_swap_total ? (float)kb_swap_used * (100.0 / (float)kb_swap_total) : 0; pct_swap = MEM_VAL(swp_TOTAL) ? (float)MEM_VAL(swp_USED) * (100.0 / (float)MEM_VAL(swp_TOTAL)) : 0;
#ifndef QUICK_GRAPHS #ifndef QUICK_GRAPHS
int num_used = (int)((pct_used * Graph_adj) + .5), int num_used = (int)((pct_used * Graph_adj) + .5),
num_misc = (int)((pct_misc * Graph_adj) + .5); num_misc = (int)((pct_misc * Graph_adj) + .5);
@ -5265,16 +5291,16 @@ numa_nope:
#endif #endif
snprintf(dual, sizeof(dual), "%s%s", used, util); snprintf(dual, sizeof(dual), "%s%s", used, util);
snprintf(util, sizeof(util), gtab[ix].swap, (int)((pct_swap * Graph_adj) + .5), gtab[ix].type); snprintf(util, sizeof(util), gtab[ix].swap, (int)((pct_swap * Graph_adj) + .5), gtab[ix].type);
prT(bfT(0), mkM(total)); prT(bfT(1), mkS(total)); prT(bfT(0), mkM(MEM_VAL(mem_TOTAL))); prT(bfT(1), mkM(MEM_VAL(swp_TOTAL)));
show_special(0, fmtmk( "%s %s:~3%#5.1f~2/%-9.9s~3[~1%-*s]~1\n%s %s:~3%#5.1f~2/%-9.9s~3[~1%-*s]~1\n" show_special(0, fmtmk( "%s %s:~3%#5.1f~2/%-9.9s~3[~1%-*s]~1\n%s %s:~3%#5.1f~2/%-9.9s~3[~1%-*s]~1\n"
, scT(label), N_txt(WORD_abv_mem_txt), pct_used + pct_misc, bfT(0), Graph_len +4, dual , scT(label), N_txt(WORD_abv_mem_txt), pct_used + pct_misc, bfT(0), Graph_len +4, dual
, scT(label), N_txt(WORD_abv_swp_txt), pct_swap, bfT(1), Graph_len +2, util)); , scT(label), N_txt(WORD_abv_swp_txt), pct_swap, bfT(1), Graph_len +2, util));
} else { } else {
unsigned long kb_main_my_misc = kb_main_buffers + kb_main_cached; unsigned long my_misc = MEM_VAL(mem_BUFFS) + MEM_VAL(mem_CACHE);
prT(bfT(0), mkM(total)); prT(bfT(1), mkM(free)); prT(bfT(0), mkM(MEM_VAL(mem_TOTAL))); prT(bfT(1), mkM(MEM_VAL(mem_FREE)));
prT(bfT(2), mkM(used)); prT(bfT(3), mkM(my_misc)); prT(bfT(2), mkM(MEM_VAL(mem_USED))); prT(bfT(3), mkM(my_misc));
prT(bfT(4), mkS(total)); prT(bfT(5), mkS(free)); prT(bfT(4), mkM(MEM_VAL(swp_TOTAL))); prT(bfT(5), mkM(MEM_VAL(swp_FREE)));
prT(bfT(6), mkS(used)); prT(bfT(7), mkM(available)); prT(bfT(6), mkM(MEM_VAL(swp_USED))); prT(bfT(7), mkM(MEM_VAL(mem_AVAIL)));
show_special(0, fmtmk(N_unq(MEMORY_lines_fmt) show_special(0, fmtmk(N_unq(MEMORY_lines_fmt)
, scT(label), N_txt(WORD_abv_mem_txt), bfT(0), bfT(1), bfT(2), bfT(3) , scT(label), N_txt(WORD_abv_mem_txt), bfT(0), bfT(1), bfT(2), bfT(3)
, scT(label), N_txt(WORD_abv_swp_txt), bfT(4), bfT(5), bfT(6), bfT(7) , scT(label), N_txt(WORD_abv_swp_txt), bfT(4), bfT(5), bfT(6), bfT(7)
@ -5284,7 +5310,6 @@ numa_nope:
#undef bfT #undef bfT
#undef scT #undef scT
#undef mkM #undef mkM
#undef mkS
#undef prT #undef prT
} // end: View_MEMORY } // end: View_MEMORY
@ -5390,7 +5415,7 @@ static const char *task_show (const WIN_t *q, const proc_t *p) {
cp = make_str(p->lxcname, W, Js, EU_LXC); cp = make_str(p->lxcname, W, Js, EU_LXC);
break; break;
case EU_MEM: case EU_MEM:
cp = scale_pcnt((float)pages2K(p->resident) * 100 / kb_main_total, W, Jn); cp = scale_pcnt((float)pages2K(p->resident) * 100 / MEM_VAL(mem_TOTAL), W, Jn);
break; break;
case EU_NCE: case EU_NCE:
cp = make_num(p->nice, W, Jn, AUTOX_NO); cp = make_num(p->nice, W, Jn, AUTOX_NO);

View File

@ -472,6 +472,7 @@ static void build_norm_nlstab (void) {
. padding with extra spaces as necessary */ . padding with extra spaces as necessary */
Norm_nlstab[WORD_abv_mem_txt] = _("Mem "); Norm_nlstab[WORD_abv_mem_txt] = _("Mem ");
Norm_nlstab[WORD_abv_swp_txt] = _("Swap"); Norm_nlstab[WORD_abv_swp_txt] = _("Swap");
Norm_nlstab[LIB_errormem_txt] = _("library failed memory stats");
} }

View File

@ -74,17 +74,17 @@ enum norm_nls {
FIND_no_next_txt, FOREST_modes_fmt, FOREST_views_txt, GET_find_str_txt, FIND_no_next_txt, FOREST_modes_fmt, FOREST_views_txt, GET_find_str_txt,
GET_max_task_fmt, GET_nice_num_fmt, GET_pid2kill_fmt, GET_pid2nice_fmt, GET_max_task_fmt, GET_nice_num_fmt, GET_pid2kill_fmt, GET_pid2nice_fmt,
GET_sigs_num_fmt, GET_user_ids_txt, HELP_cmdline_fmt, IRIX_curmode_fmt, GET_sigs_num_fmt, GET_user_ids_txt, HELP_cmdline_fmt, IRIX_curmode_fmt,
LIMIT_exceed_fmt, MISSING_args_fmt, NAME_windows_fmt, NOT_onsecure_txt, LIB_errormem_txt, LIMIT_exceed_fmt, MISSING_args_fmt, NAME_windows_fmt,
NOT_smp_cpus_txt, NUMA_nodebad_txt, NUMA_nodeget_fmt, NUMA_nodenam_fmt, NOT_onsecure_txt, NOT_smp_cpus_txt, NUMA_nodebad_txt, NUMA_nodeget_fmt,
NUMA_nodenot_txt, OFF_one_word_txt, ON_word_only_txt, OSEL_casenot_txt, NUMA_nodenam_fmt, NUMA_nodenot_txt, OFF_one_word_txt, ON_word_only_txt,
OSEL_caseyes_txt, OSEL_errdelm_fmt, OSEL_errdups_txt, OSEL_errvalu_fmt, OSEL_casenot_txt, OSEL_caseyes_txt, OSEL_errdelm_fmt, OSEL_errdups_txt,
OSEL_prompts_fmt, OSEL_statlin_fmt, RC_bad_entry_fmt, RC_bad_files_fmt, OSEL_errvalu_fmt, OSEL_prompts_fmt, OSEL_statlin_fmt, RC_bad_entry_fmt,
SCROLL_coord_fmt, SELECT_clash_txt, THREADS_show_fmt, TIME_accumed_fmt, RC_bad_files_fmt, SCROLL_coord_fmt, SELECT_clash_txt, THREADS_show_fmt,
UNKNOWN_cmds_txt, UNKNOWN_opts_fmt, USAGE_abbrev_txt, WORD_abv_mem_txt, TIME_accumed_fmt, UNKNOWN_cmds_txt, UNKNOWN_opts_fmt, USAGE_abbrev_txt,
WORD_abv_swp_txt, WORD_allcpus_txt, WORD_another_txt, WORD_eachcpu_fmt, WORD_abv_mem_txt, WORD_abv_swp_txt, WORD_allcpus_txt, WORD_another_txt,
WORD_exclude_txt, WORD_include_txt, WORD_noneone_txt, WORD_process_txt, WORD_eachcpu_fmt, WORD_exclude_txt, WORD_include_txt, WORD_noneone_txt,
WORD_threads_txt, WRITE_rcfile_fmt, WRONG_switch_fmt, XTRA_badflds_fmt, WORD_process_txt, WORD_threads_txt, WRITE_rcfile_fmt, WRONG_switch_fmt,
XTRA_fixwide_fmt, XTRA_warncfg_txt, XTRA_winsize_txt, XTRA_badflds_fmt, XTRA_fixwide_fmt, XTRA_warncfg_txt, XTRA_winsize_txt,
#ifndef INSP_OFFDEMO #ifndef INSP_OFFDEMO
YINSP_demo01_txt, YINSP_demo02_txt, YINSP_demo03_txt, YINSP_deqfmt_txt, YINSP_demo01_txt, YINSP_demo02_txt, YINSP_demo03_txt, YINSP_deqfmt_txt,
YINSP_deqtyp_txt, YINSP_dstory_txt, YINSP_deqtyp_txt, YINSP_dstory_txt,