PMGENMAP(1)

πŸ“¦
version 7.2.2 Β· 3 versions
, in arch rolling, centos-stream 10, centos-stream 9, debian trixie, fedora 43, fedora 44, ubuntu questing, ubuntu resolute, ubuntu stonking

✨ pmgenmap ✨

okay bestie so this is pmgenmap, from the General Commands Manual (that's section 1, the "commands you actually run" girlies πŸ’…). She generates C code so you never have to hand-type a metric name again. periodt.


🌸 SYNOPSIS 🌸

pmgenmap [infile]

πŸŽ€ DESCRIPTION πŸŽ€

So here's the vibe: you hand pmgenmap one or more lists of metric names β€” either in infile, or just piped in on standard input if you're feeling feral β€” and it spits out C declarations plus cpp(1) macros on standard output. All of it suitable for use across the Performance Metrics Programming Interface, aka the PMAPI. πŸ‘‘

And like, why do you care? Because the declarations it produces make coding for client applications that use the PMAPI so much simpler. It's giving "let the tool do the boring part." 🫢

Your input should be one or more lists of metric names shaped like this:

     listname {
         metricname1 symbolname1
         metricname2 symbolname2
         ...
     }

and that turns into C and cpp(1) declarations shaped like this:

     char *listname[] = {
     #define symbolname1 0
         "metricname1",
     #define symbolname2 1
         "metricname2",
         ...
     };

The array declarations it makes are literally suitable as parameters to pmLookupName(3), and those #defined constants can be used to index the vsets in the pmResult structure that comes back from a pmFetch(3) call. no cap, that's the whole trick ✨

Now, ground rules, and yes they matter πŸ™ˆ β€” listname has to conform to the C identifier naming rules, every symbolname has to conform to the cpp(1) macro naming rules, and each metricname is expected to be a valid performance metrics name (go read PMNS(5) for the deets, iykyk).

Your input can also have sh-style comment lines β€” that's a # as the first non-blank character of a line β€” and those get translated on output into either single line or multi-line C comments in the K&R style. iconic honestly. So if your input looks like:

# leading block of multi-line comments
# initialization group
foo {
        a.b.c   ONE
        d.e.f.g TWO
        # embedded block of multi-lines
        # comments and boring pad text
        xx.yy.zz        THREE
}

# trailing single line comment

then the output is:

/*
 * leading block of multi-line comments
 * initialization group
 */
char *foo[] = {
#define ONE 0
        "a.b.c",
#define TWO 1
        "d.e.f.g",
/*
 * embedded block of multi-lines
 * comments and boring pad text
 */
#define THREE 2
        "xx.yy.zz",

};

/* trailing single line comment */

see? she ATE that. πŸ”₯


πŸ¦‹ EXAMPLES πŸ¦‹

for brevity we have removed the error handling code, and assumed the chosen metrics do not have multiple values. (yes, "for brevity," the classic. 😭)

The input file:

mystats {
    kernel.percpu.cpu.idle     IDLE
    kernel.percpu.cpu.sys      SYS
    kernel.percpu.cpu.user     USER
    hinv.ncpu                       NCPU
}

produces the following C code, suitable for #include-ing:

/*
 * Performance Metrics Name Space Map
 * Built by pmgenmap from the file
 * mystats.metrics
 * on Wed Dec 28 19:44:17 EST 1994
 *
 * Do not edit this file!
 */

char *mystats[] = {
#define IDLE    0
        "kernel.percpu.cpu.idle",
#define SYS     1
        "kernel.percpu.cpu.sys",
#define USER    2
        "kernel.percpu.cpu.user",
#define NCPU    3
        "hinv.ncpu",

};

Using the code generated by pmgenmap, we are now able to easily obtain metrics from the Performance Metrics Collection Subsystem (PMCS) as follows:

#define MAX_PMID 4

    int         trip = 0;
    int         numpmid = sizeof(mystats)/sizeof(mystats[0]);
    double      duration;
    pmResult    *resp;
    pmResult    *prev;
    pmID        pmidlist[MAX_PMID];

    pmNewContext(PM_CONTEXT_HOST, "localhost");
    pmLookupName(numpmid, mystats, pmidlist);
    pmFetch(numpmid, pmidlist, &resp);

    printf("%d CPUs: %d usr   %d sys   %d   idle0,
           resp->vset[NCPU]->vlist[0].value.lval,
           resp->vset[USER]->vlist[0].value.lval,
           resp->vset[SYS]->vlist[0].value.lval,
           resp->vset[IDLE]->vlist[0].value.lval);
⚠️ okay listen β€” some calls to ensure portability have been removed from the code above for the sake of clarity. The example above should not be used as a template for programming. In particular, the raw values of the metrics were used when pmLookupDesc(3) should have been called to determine the semantics of each metric. do NOT copy this into prod bestie I am begging πŸ™ˆ

More complete examples that demonstrate the use of pmgenmap which may be used as a basis for program development are included in the PCP demos, e.g. $PCP_DEMOS_DIR/pmclient. go look, it's worth it. πŸ’–


πŸ“ FILES πŸ“

  • $PCP_VAR_DIR/pmns/* β€” default PMNS specification files

🌈 PCP ENVIRONMENT 🌈

Environment variables with the prefix PCP_ are used to parameterize the file and directory names used by PCP. On each installation, the file /etc/pcp.conf contains the local values for these variables. The $PCP_CONF variable may be used to specify an alternative configuration file, as described in pcp.conf(5).


πŸ’œ SEE ALSO πŸ’œ

cpp(1), PMAPI(3), pmFetch(3), pmLookupName(3), pmNewContext(3), pcp.conf(5), pcp.env(5) and PMNS(5).


and that's the whole page, bestie! this one's brought to you by Performance Co-Pilot / PCP, filed under PMGENMAP(1) β€” go forth and generate your C code, you absolute main character πŸ‘‘πŸ’–

πŸ“¦ where this page comes from