]> granicus.if.org Git - procps-ng/commitdiff
top: exploit the new library API for memory statistics
authorJim Warner <james.warner@comcast.net>
Sun, 28 Jun 2015 05:00:00 +0000 (00:00 -0500)
committerCraig Small <csmall@enc.com.au>
Mon, 29 Jun 2015 11:29:33 +0000 (21:29 +1000)
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>
top/top.c
top/top_nls.c
top/top_nls.h

index 056f64445da2cd67e2882a74063cb5d1b466f07f..b4dd7c3245b8365e64962e5cdfc9cfaec15825de 100644 (file)
--- a/top/top.c
+++ b/top/top.c
@@ -50,6 +50,7 @@
 #include "../include/nls.h"
 
 #include "../proc/devname.h"
+#include "../proc/meminfo.h"
 #include "../proc/procps.h"
 #include "../proc/readproc.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 const char Graph_blks[] = "                                                                                                    ";
 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
 \f
 /*######  Sort callbacks  ################################################*/
 
@@ -2697,7 +2718,9 @@ static void sysinfo_refresh (int forced) {
 
    /*** hotplug_acclimated ***/
    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;
    }
 #ifndef PRETEND8CPUS
@@ -3293,6 +3316,10 @@ static void before (char *me) {
    i = page_bytes; // from sysinfo.c, at lib init
    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
    // prep for HST_t's put/get hashing optimizations
    for (i = 0; i < HHASH_SIZ; i++) HHash_nul[i] = -1;
@@ -5207,8 +5234,7 @@ numa_nope:
    if (isROOM(View_MEMORY, 2)) {
     #define bfT(n)  buftab[n].buf
     #define scT(e)  scaletab[Rc.summ_mscale]. e
-    #define mkM(x) (float)kb_main_ ## x / scT(div)
-    #define mkS(x) (float)kb_swap_ ## x / scT(div)
+    #define mkM(x) (float) x / scT(div)
     #define prT(b,z) { if (9 < snprintf(b, 10, scT(fmts), z)) b[8] = '+'; }
       static struct {
          float div;
@@ -5246,13 +5272,13 @@ numa_nope:
          };
          char used[SMLBUFSIZ], util[SMLBUFSIZ], dual[MEDBUFSIZ];
          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
-               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
-               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
-               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
          int num_used = (int)((pct_used * Graph_adj) + .5),
              num_misc = (int)((pct_misc * Graph_adj) + .5);
@@ -5265,16 +5291,16 @@ numa_nope:
 #endif
          snprintf(dual, sizeof(dual), "%s%s", used, util);
          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"
             , 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));
       } else {
-         unsigned long kb_main_my_misc = kb_main_buffers + kb_main_cached;
-         prT(bfT(0), mkM(total)); prT(bfT(1), mkM(free));
-         prT(bfT(2), mkM(used));  prT(bfT(3), mkM(my_misc));
-         prT(bfT(4), mkS(total)); prT(bfT(5), mkS(free));
-         prT(bfT(6), mkS(used));  prT(bfT(7), mkM(available));
+         unsigned long my_misc = MEM_VAL(mem_BUFFS) + MEM_VAL(mem_CACHE);
+         prT(bfT(0), mkM(MEM_VAL(mem_TOTAL))); prT(bfT(1), mkM(MEM_VAL(mem_FREE)));
+         prT(bfT(2), mkM(MEM_VAL(mem_USED)));  prT(bfT(3), mkM(my_misc));
+         prT(bfT(4), mkM(MEM_VAL(swp_TOTAL))); prT(bfT(5), mkM(MEM_VAL(swp_FREE)));
+         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)
             , 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)
@@ -5284,7 +5310,6 @@ numa_nope:
     #undef bfT
     #undef scT
     #undef mkM
-    #undef mkS
     #undef prT
    } // 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);
             break;
          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;
          case EU_NCE:
             cp = make_num(p->nice, W, Jn, AUTOX_NO);
index 1928b17239ef9a0bcd17166d48f518bee64d20fc..01f9f88c60c113be3fefbfcc724b923ed6941112 100644 (file)
@@ -472,6 +472,7 @@ static void build_norm_nlstab (void) {
    .                 padding with extra spaces as necessary */
    Norm_nlstab[WORD_abv_mem_txt] = _("Mem ");
    Norm_nlstab[WORD_abv_swp_txt] = _("Swap");
+   Norm_nlstab[LIB_errormem_txt] = _("library failed memory stats");
 }
 
 
index 896ed9217ce24bb7e1fcd403105193492e6218a1..5f3d7b5169fd9b05c61c1bf1f282e4cbd0ed5bd5 100644 (file)
@@ -74,17 +74,17 @@ enum norm_nls {
    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_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,
-   NOT_smp_cpus_txt, NUMA_nodebad_txt, NUMA_nodeget_fmt, NUMA_nodenam_fmt,
-   NUMA_nodenot_txt, OFF_one_word_txt, ON_word_only_txt, OSEL_casenot_txt,
-   OSEL_caseyes_txt, OSEL_errdelm_fmt, OSEL_errdups_txt, OSEL_errvalu_fmt,
-   OSEL_prompts_fmt, OSEL_statlin_fmt, RC_bad_entry_fmt, RC_bad_files_fmt,
-   SCROLL_coord_fmt, SELECT_clash_txt, THREADS_show_fmt, TIME_accumed_fmt,
-   UNKNOWN_cmds_txt, UNKNOWN_opts_fmt, USAGE_abbrev_txt, WORD_abv_mem_txt,
-   WORD_abv_swp_txt, WORD_allcpus_txt, WORD_another_txt, WORD_eachcpu_fmt,
-   WORD_exclude_txt, WORD_include_txt, WORD_noneone_txt, WORD_process_txt,
-   WORD_threads_txt, WRITE_rcfile_fmt, WRONG_switch_fmt, XTRA_badflds_fmt,
-   XTRA_fixwide_fmt, XTRA_warncfg_txt, XTRA_winsize_txt,
+   LIB_errormem_txt, LIMIT_exceed_fmt, MISSING_args_fmt, NAME_windows_fmt,
+   NOT_onsecure_txt, NOT_smp_cpus_txt, NUMA_nodebad_txt, NUMA_nodeget_fmt,
+   NUMA_nodenam_fmt, NUMA_nodenot_txt, OFF_one_word_txt, ON_word_only_txt,
+   OSEL_casenot_txt, OSEL_caseyes_txt, OSEL_errdelm_fmt, OSEL_errdups_txt,
+   OSEL_errvalu_fmt, OSEL_prompts_fmt, OSEL_statlin_fmt, RC_bad_entry_fmt,
+   RC_bad_files_fmt, SCROLL_coord_fmt, SELECT_clash_txt, THREADS_show_fmt,
+   TIME_accumed_fmt, UNKNOWN_cmds_txt, UNKNOWN_opts_fmt, USAGE_abbrev_txt,
+   WORD_abv_mem_txt, WORD_abv_swp_txt, WORD_allcpus_txt, WORD_another_txt,
+   WORD_eachcpu_fmt, WORD_exclude_txt, WORD_include_txt, WORD_noneone_txt,
+   WORD_process_txt, WORD_threads_txt, WRITE_rcfile_fmt, WRONG_switch_fmt,
+   XTRA_badflds_fmt, XTRA_fixwide_fmt, XTRA_warncfg_txt, XTRA_winsize_txt,
 #ifndef INSP_OFFDEMO
    YINSP_demo01_txt, YINSP_demo02_txt, YINSP_demo03_txt, YINSP_deqfmt_txt,
    YINSP_deqtyp_txt, YINSP_dstory_txt,