[Orca-checkins] r400 - in trunk/orca: data_gatherers/orcallator lib/SE/3.2.1 lib/SE/3.3 lib/SE/3.3.1
dmberezin at hotmail.com
dmberezin at hotmail.com
Mon Nov 1 14:05:40 PST 2004
Author: dmberezin at hotmail.com
Date: Mon Nov 1 14:00:49 2004
New Revision: 400
Added:
trunk/orca/lib/SE/3.2.1/workinfo_class.se
trunk/orca/lib/SE/3.3.1/workinfo_class.se
trunk/orca/lib/SE/3.3/workinfo_class.se
Modified:
trunk/orca/data_gatherers/orcallator/orcallator.se
Log:
Add workload data gathering support
* lib/SE/3.3.1/workinfo_class.se
* lib/SE/3.2.1/workinfo_class.se
* lib/SE/3.3/workinfo_class.se
This is a new SE class, based on workload class included in SEToolkit, which
allows for integration of workload data gathering into orcallator.se.
Set WORKLOAD_INFO and WORKLOAD_FIRSTMATCH to define data collection rules.
* data_gatherers/orcallator/orcallator.se
(measure_workload): New function to collect workload data. Define
WATCH_WORKLOAD to activate it. Define WORKLOAD_TOTAL to collect total process
data with workinfo class.
Modified: trunk/orca/data_gatherers/orcallator/orcallator.se
==============================================================================
--- trunk/orca/data_gatherers/orcallator/orcallator.se (original)
+++ trunk/orca/data_gatherers/orcallator/orcallator.se Mon Nov 1 14:00:49 2004
@@ -97,6 +97,10 @@
#include <tcp_class.se>
#include <tcp_rules.se>
+#ifdef WATCH_WORKLOAD
+#include <workinfo_class.se>
+#endif
+
#ifdef WATCH_MOUNTS
#include <mnt_class.se>
#include <statvfs.se>
@@ -1026,6 +1030,11 @@
#ifdef WATCH_PAGES
measure_pages();
#endif
+
+ // Get workload data
+#ifdef WATCH_WORKLOAD
+ measure_workload();
+#endif
}
/*
@@ -2406,3 +2415,45 @@
#endif
}
#endif
+
+#ifdef WATCH_WORKLOAD
+measure_workload()
+{
+ work_info_class_t ww;
+ double millisecs_per_switch;
+
+ ww.number = -1;
+#ifndef WORKLOAD_TOTAL
+ refresh$(ww);
+#endif // WORKLOAD_TOTAL
+ for (refresh$(ww); ww.number != -1; refresh$(ww)) {
+ put_output(sprintf("%s_cnt", ww.w.name), sprintf("%4d", ww.w.count));
+ put_output(sprintf("%s_lwpcnt", ww.w.name), sprintf("%4d", ww.w.info.lwp_count));
+
+ if (ww.w.cnt == 0) {
+ millisecs_per_switch = ww.w.info.vcontexts + ww.w.info.icontexts;
+ if (millisecs_per_switch > 0.0) {
+ millisecs_per_switch = 1000 * (ww.w.info.user_time + ww.w.info.system_time) / millisecs_per_switch;
+ }
+
+ put_output(sprintf("%s_usr%%", ww.w.name), sprintf("%6.1f", 100.0*ww.w.info.user_time));
+ put_output(sprintf("%s_sys%%", ww.w.name), sprintf("%6.1f", 100.0*(ww.w.info.system_time +
+ ww.w.info.trap_time)));
+ put_output(sprintf("%s_cpwt%%", ww.w.name), sprintf("%5.0f", 100.0*(ww.w.info.cpu_wait_time)));
+ put_output(sprintf("%s_chld%%", ww.w.name), sprintf("%5.0f", 100.0*ww.w.info.child_time));
+ put_output(sprintf("%s_sizeM", ww.w.name), sprintf("%7d", ww.w.info.vmem_size/1024));
+ put_output(sprintf("%s_pf", ww.w.name), sprintf("%4d", ww.w.info.maj_faults));
+ put_output(sprintf("%s_pgwt%%", ww.w.name), sprintf("%6.0f", 100.0*(ww.w.info.text_pf_time +
+ ww.w.info.data_pf_time +
+ ww.w.info.kernel_pf_time)));
+ put_output(sprintf("%s_ulkwt%%", ww.w.name), sprintf("%6.0f", 100.0*ww.w.info.user_lock_time));
+ put_output(sprintf("%s_ioK", ww.w.name), sprintf("%6.0f", ww.w.info.charios/1024.0));
+ put_output(sprintf("%s_sysc", ww.w.name), sprintf("%6d", ww.w.info.syscalls));
+ put_output(sprintf("%s_vctx", ww.w.name), sprintf("%6d", ww.w.info.vcontexts));
+ put_output(sprintf("%s_ictx", ww.w.name), sprintf("%6d", ww.w.info.icontexts));
+ put_output(sprintf("%s_msps", ww.w.name), sprintf("%6.2f", millisecs_per_switch));
+ }
+ }
+ return;
+}
+#endif // WATCH_WORKLOAD
Added: trunk/orca/lib/SE/3.2.1/workinfo_class.se
==============================================================================
--- (empty file)
+++ trunk/orca/lib/SE/3.2.1/workinfo_class.se Mon Nov 1 14:00:49 2004
@@ -0,0 +1,341 @@
+#ifndef _WORKINFO_CLASS_SE_
+#define _WORKINFO_CLASS_SE_
+
+/***********************************************************
+* *
+* Workinfo class is based on Adrian's workload class *
+* *
+***********************************************************/
+
+/**************************************************************************
+Usage notes -
+This class is designed to collect process statistics for any group of
+processes defined by executed command, command arguments, executing user,
+and processor set binding.
+This class looks for WORKLOAD_INFO environment variable to initialize.
+
+To initialize workload information set WORKLOAD_INFO in the environment
+in the following way:
+WORKLOAD_INFO=name,command,args,user,exact,cnt,pset;...;...
+export WORKLOAD_INFO
+
+DO NOT use quotes ("") around string values (name,command,args,user).
+To skip one of the parameters use a SINGLE space. Missing or skipped
+parameters are ignored during process matching.
+Missing name defaults to WorkloadN, where N is workload number.
+Missing command, args, or user are skipped.
+By default pset is set to -1, cnt and exact are set to 0;
+
+Set pset to -1 to unset matching on processor set.
+Set exact to non-zero for exact matching, or 0 for pattern matching.
+Set cnt to non-zero to only count the number of processes and threads
+in a given workload. Other data is neither collected nor printed.
+
+If there is not enough process parameters defined in a set, workload
+parameters initialized in order with supplied data and the rest of the
+parameters are set to their default values.
+
+Set WORKLOAD_FIRSTMATCH=0 in the environment to match each process
+for all workloads.
+Set WORKLOAD_FIRSTMATCH=1 in the environment to match each process
+for one workload only.
+
+If WORKINFO_PRINT is defined, workload information is printed after
+initialization to allow for verification of workload data.
+
+Examples:
+export WORKLOAD_INFO='SE,se.sparc'
+Defines one workload with the name SE, command se.sparc, args and user
+empty string, exact 0 (match patterns), and no processor set.
+
+export WORKLOAD_INFO='SE,se.sparc, , ,1'
+The same as the above except matching is exact
+
+export WORKLOAD_INFO='SE,se.sparc;Ora, , ,oracle,1,1'
+Defines two workloads. In addition to SE workload, defines a workload named Ora
+that counts all processes owned by user oracle.
+
+Class usage example:
+########################################
+
+#include <workinfo_class.se>
+
+measure_workload()
+{
+ work_info_class_t ww;
+
+ ww.number = -1;
+#ifdef WORKLOAD_NO_TOTAL
+ refresh$(ww);
+#endif // WORKLOAD_NO_TOTAL
+ for (refresh$(ww); ww.number != -1; refresh$(ww)) {
+ printf("Wrkld=%s, number of procs=%d\n",ww.w.name,ww.w.count);
+ printf("Wrkld=%s, number of threads=%d\n",ww.w.name,ww.w.info.lwp_count);
+ // Get other data if not just counting processes
+ if (ww.w.cnt == 0) {
+ printf("Wrkld=%s, cpu_usr=%d\n",ww.w.name,100.0*ww.w.info.user_time);
+ printf("Wrkld=%s, cpu_sys=%d\n",ww.w.name,100.0*(ww.w.info.system_time+
+ ww.w.info.trap_time));
+ printf("Wrkld=%s, cpu_wait=%d\n",ww.w.name,100.0*ww.w.info.cpu_wait_time);
+ <...>
+ }
+ }
+<...>
+}
+########################################
+
+**************************************************************************/
+
+#include <unistd.se>
+#include <dirent.se>
+#include <fcntl.se>
+#include <proc.se>
+#include <process_class.se>
+#include <pwd.se>
+
+struct work_info_t {
+ string name; // Used by orcallator for header names for this workload
+ string command; // String to match against command name
+ string args; // String to match against command args
+ string user; // String to match against user name
+ int exact; // Set to match exact names instead of patterns
+ int cnt; // Set to count processes and threads only
+ int pset; // Processor set to match against
+ int count; // Number of processes that matched
+ proc_class_t info; // Use same data type to accumulate data
+};
+
+int match_proc(proc_class_t p, work_info_t w) {
+ passwd_t pw;
+ pointer_t ppw;
+
+ if (w.command != "") { // If command is defined and...
+ if(w.exact == 0) { // pattern matching and...
+ if(!(p.fname =~ w.command)) { // pattern does not match -
+ return 0; // exit and signal no match
+ }
+ } else { // exact command matching and...
+ if(p.fname != w.command) { // command does not match -
+ return 0; // exit and signal no match
+ }
+ }
+ }
+
+ if (w.args != "") { // If args is defined and...
+ if(w.exact == 0) { // pattern matching and...
+ if(!(p.args =~ w.args)) { // pattern does not match -
+ return 0; // exit and signal no match
+ }
+ } else { // exact args matching and...
+ if(p.args != w.args) { // args does not match -
+ return 0; // exit and signal no match
+ }
+ }
+ }
+
+ if (w.user != "") { // If user name is defined and...
+ ppw = getpwuid(p.uid); // Get user information for this process
+ if (ppw == 0) { // If unsuccessful...
+ return 0; // return no match
+ }
+ pw = *((passwd_t *) ppw);
+ if(w.exact == 0) { // pattern matching and...
+ if(!(pw.pw_name =~ w.user)) { // pattern does not match -
+ return 0; // exit and signal no match
+ }
+ } else { // exact user name matching and...
+ if(pw.pw_name != w.user) { // user name does not match -
+ return 0; // exit and signal no match
+ }
+ }
+ }
+
+ if ((w.pset != -1) && (p.bindpset != w.pset)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+class work_info_class_t {
+ int number; // Current workload
+ work_info_t w; // Data for current workload
+
+ work_info$() {
+ work_info_t wi[]; // Workload data dynamic array
+ int wc = 0; // Number of workloads
+ int firstmatch; // Set to use first workload that matches only
+ string fmstring;
+ proc_class_t pp; // Underlying process class data (snapshot)
+ proc_class_t ppzero; // Used to zero out by copying
+ double iv;
+ int i;
+ string wstring;
+ string wstr;
+ string dstr;
+ ulong pwstring;
+ ulong pwstr;
+ int initialized = 0;
+
+ if (initialized == 0) { // Initialize class
+ refresh$(pp); // Setup proc_class
+ fmstring = getenv("WORKLOAD_FIRSTMATCH"); // Load user defined matching policy
+ wstring = getenv("WORKLOAD_INFO"); // Load user defined data for matching
+
+ // Set matching policy
+ if (fmstring != nil) {
+ firstmatch = atoi(fmstring);
+ } else {
+ // Default to each process in one workload only
+ firstmatch = 1;
+ }
+
+ // Allocate memory for collecting totals
+ wi = new work_info_t[1];
+ wi[wc].name = "Total";
+ wi[wc].command = "";
+ wi[wc].args = "";
+ wi[wc].user = "";
+ wi[wc].pset = -1;
+
+ // Parse wstring into individual workloads
+ for (wstr = strtok_r(wstring, ";", &pwstring); wstr != nil; wstr = strtok_r(nil, ";", &pwstring)) {
+ // Allocate memory for this workload
+ wi = renew wi[++wc+1];
+ wi[wc].name = strtok_r(wstr, ",", &pwstr); // Get name
+ if (wi[wc].name == nil || wi[wc].name == " ") {
+ wi[wc].name = sprintf("Workload%d", wc);
+ }
+ wi[wc].command = strtok_r(nil, ",", &pwstr); // Get command
+ if (wi[wc].command == nil || wi[wc].command == " ") {
+ wi[wc].command = "";
+ }
+ wi[wc].args = strtok_r(nil, ",", &pwstr); // Get args
+ if (wi[wc].args == nil || wi[wc].args == " ") {
+ wi[wc].args = "";
+ }
+ wi[wc].user = strtok_r(nil, ",", &pwstr); // Get user
+ if (wi[wc].user == nil || wi[wc].user == " ") {
+ wi[wc].user = "";
+ }
+ dstr = strtok_r(nil, ",", &pwstr); // Get exact
+ if (dstr != nil) {
+ wi[wc].exact = atoi(dstr);
+ }
+ dstr = strtok_r(nil, ",", &pwstr); // Get cnt
+ if (dstr != nil) {
+ wi[wc].cnt = atoi(dstr);
+ }
+ dstr = strtok_r(nil, ",", &pwstr); // Get pset
+ if (dstr == nil || dstr == " ") {
+ wi[wc].pset = -1;
+ } else {
+ wi[wc].pset = atoi(dstr);
+ }
+ }
+
+#ifdef WORKINFO_PRINT
+ printf("\nWorkinfo class is initialized with the following data\n");
+ printf("Number of workloads = %d, firstmatch = %d (%s)\n",
+ wc, firstmatch, (firstmatch == 0 ? "Match all workloads" : "Match each process only once"));
+ for(i=1; i <= wc; i++) {
+ printf("Workload number %3d\n-------------------\n", i);
+ printf("name .................... %s\n", wi[i].name);
+ printf("command ................. %s\n", wi[i].command);
+ printf("args .................... %s\n", wi[i].args);
+ printf("user .................... %s\n", wi[i].user);
+ printf("exact ................... %d\n", wi[i].exact);
+ printf("pset .................... %d\n", wi[i].pset);
+ printf("Only count the number of\nprocesses and threads ... %s\n\n",
+ (wi[i].cnt == 0 ? "No" : "Yes"));
+ }
+#endif // WORKINFO_PRINT
+
+ number = -1;
+ initialized = 1;
+ return;
+ }
+
+ if (number != -1) { // Data is available
+ if (number < wc) {
+ w = wi[++number]; // Return next workload data
+ } else {
+ w = wi[0]; // Set w to Total data
+ number = -1; // Signal end of data
+ }
+ return;
+ }
+
+ for(i=0; i <= wc; i++) { // Reset counters
+ wi[i].count = 0;
+ wi[i].info = ppzero; // Not easy to use memset instead
+ }
+ refresh$(pp); // Get the snapshot
+ while (pp.index$ != -1) {
+ if (pp.termination != 0.0) {
+ continue; // Don't add in dead processes
+ }
+ for(i=0; i <= wc; i++) {
+ if (i == 0 || // Accumulate totals
+ (match_proc(pp, wi[i]) != 0)) {
+ wi[i].info.interval = pp.interval; // Take the last interval seen
+ iv = pp.interval;
+ if (iv == 0.0) { iv = 1.0; } // Safety net
+ if (pp.creation < wi[i].info.creation) { // Take the earliest creation
+ wi[i].info.creation = pp.creation;
+ }
+ if (wi[i].cnt == 0) {
+ // Track individual times
+ wi[i].info.lasttime = pp.lasttime;
+ wi[i].info.total_user += pp.total_user;
+ wi[i].info.total_system += pp.total_system;
+ wi[i].info.total_child += pp.total_child;
+ // Intervals vary, so accumulate here
+ wi[i].info.user_time += pp.user_time/iv;
+ wi[i].info.system_time += pp.system_time/iv;
+ wi[i].info.trap_time += pp.trap_time/iv;
+ wi[i].info.child_time += pp.child_time/iv;
+ wi[i].info.text_pf_time += pp.text_pf_time/iv;
+ wi[i].info.data_pf_time += pp.data_pf_time/iv;
+ wi[i].info.kernel_pf_time += pp.kernel_pf_time/iv;
+ wi[i].info.user_lock_time += pp.user_lock_time/iv;
+ wi[i].info.sleep_time += pp.sleep_time/iv;
+ wi[i].info.cpu_wait_time += pp.cpu_wait_time/iv;
+ wi[i].info.stoptime += pp.stoptime/iv;
+ wi[i].info.syscalls += pp.syscalls/iv;
+ wi[i].info.inblocks += pp.inblocks/iv;
+ wi[i].info.outblocks += pp.outblocks/iv;
+ // Next four are sizes not rates
+ wi[i].info.vmem_size += pp.vmem_size;
+ wi[i].info.rmem_size += pp.rmem_size;
+#ifdef XMAP
+ wi[i].info.pmem_size += pp.pmem_size;
+ wi[i].info.smem_size += pp.smem_size;
+#endif
+ wi[i].info.maj_faults += pp.maj_faults/iv;
+ wi[i].info.min_faults += pp.min_faults/iv;
+ wi[i].info.total_swaps += pp.total_swaps/iv;
+ wi[i].info.messages += pp.messages/iv;
+ wi[i].info.signals += pp.signals/iv;
+ wi[i].info.vcontexts += pp.vcontexts/iv;
+ wi[i].info.icontexts += pp.icontexts/iv;
+ wi[i].info.charios += pp.charios/iv;
+ // Divide these three by wi[i].count
+ wi[i].info.priority += pp.priority;
+ wi[i].info.niceness += pp.niceness;
+ }
+ wi[i].info.lwp_count += pp.lwp_count;
+ wi[i].count++;
+ if (firstmatch == 1 && i > 0) { // First match only counts
+ break;
+ }
+ }
+ }
+ refresh$(pp); // Next process
+ }
+ number = 0;
+ w = wi[number];
+ }
+};
+
+#endif
Added: trunk/orca/lib/SE/3.3.1/workinfo_class.se
==============================================================================
--- (empty file)
+++ trunk/orca/lib/SE/3.3.1/workinfo_class.se Mon Nov 1 14:00:49 2004
@@ -0,0 +1,341 @@
+#ifndef _WORKINFO_CLASS_SE_
+#define _WORKINFO_CLASS_SE_
+
+/***********************************************************
+* *
+* Workinfo class is based on Adrian's workload class *
+* *
+***********************************************************/
+
+/**************************************************************************
+Usage notes -
+This class is designed to collect process statistics for any group of
+processes defined by executed command, command arguments, executing user,
+and processor set binding.
+This class looks for WORKLOAD_INFO environment variable to initialize.
+
+To initialize workload information set WORKLOAD_INFO in the environment
+in the following way:
+WORKLOAD_INFO=name,command,args,user,exact,cnt,pset;...;...
+export WORKLOAD_INFO
+
+DO NOT use quotes ("") around string values (name,command,args,user).
+To skip one of the parameters use a SINGLE space. Missing or skipped
+parameters are ignored during process matching.
+Missing name defaults to WorkloadN, where N is workload number.
+Missing command, args, or user are skipped.
+By default pset is set to -1, cnt and exact are set to 0;
+
+Set pset to -1 to unset matching on processor set.
+Set exact to non-zero for exact matching, or 0 for pattern matching.
+Set cnt to non-zero to only count the number of processes and threads
+in a given workload. Other data is neither collected nor printed.
+
+If there is not enough process parameters defined in a set, workload
+parameters initialized in order with supplied data and the rest of the
+parameters are set to their default values.
+
+Set WORKLOAD_FIRSTMATCH=0 in the environment to match each process
+for all workloads.
+Set WORKLOAD_FIRSTMATCH=1 in the environment to match each process
+for one workload only.
+
+If WORKINFO_PRINT is defined, workload information is printed after
+initialization to allow for verification of workload data.
+
+Examples:
+export WORKLOAD_INFO='SE,se.sparc'
+Defines one workload with the name SE, command se.sparc, args and user
+empty string, exact 0 (match patterns), and no processor set.
+
+export WORKLOAD_INFO='SE,se.sparc, , ,1'
+The same as the above except matching is exact
+
+export WORKLOAD_INFO='SE,se.sparc;Ora, , ,oracle,1,1'
+Defines two workloads. In addition to SE workload, defines a workload named Ora
+that counts all processes owned by user oracle.
+
+Class usage example:
+########################################
+
+#include <workinfo_class.se>
+
+measure_workload()
+{
+ work_info_class_t ww;
+
+ ww.number = -1;
+#ifdef WORKLOAD_NO_TOTAL
+ refresh$(ww);
+#endif // WORKLOAD_NO_TOTAL
+ for (refresh$(ww); ww.number != -1; refresh$(ww)) {
+ printf("Wrkld=%s, number of procs=%d\n",ww.w.name,ww.w.count);
+ printf("Wrkld=%s, number of threads=%d\n",ww.w.name,ww.w.info.lwp_count);
+ // Get other data if not just counting processes
+ if (ww.w.cnt == 0) {
+ printf("Wrkld=%s, cpu_usr=%d\n",ww.w.name,100.0*ww.w.info.user_time);
+ printf("Wrkld=%s, cpu_sys=%d\n",ww.w.name,100.0*(ww.w.info.system_time+
+ ww.w.info.trap_time));
+ printf("Wrkld=%s, cpu_wait=%d\n",ww.w.name,100.0*ww.w.info.cpu_wait_time);
+ <...>
+ }
+ }
+<...>
+}
+########################################
+
+**************************************************************************/
+
+#include <unistd.se>
+#include <dirent.se>
+#include <fcntl.se>
+#include <proc.se>
+#include <process_class.se>
+#include <pwd.se>
+
+struct work_info_t {
+ string name; // Used by orcallator for header names for this workload
+ string command; // String to match against command name
+ string args; // String to match against command args
+ string user; // String to match against user name
+ int exact; // Set to match exact names instead of patterns
+ int cnt; // Set to count processes and threads only
+ int pset; // Processor set to match against
+ int count; // Number of processes that matched
+ proc_class_t info; // Use same data type to accumulate data
+};
+
+int match_proc(proc_class_t p, work_info_t w) {
+ passwd_t pw;
+ pointer_t ppw;
+
+ if (w.command != "") { // If command is defined and...
+ if(w.exact == 0) { // pattern matching and...
+ if(!(p.fname =~ w.command)) { // pattern does not match -
+ return 0; // exit and signal no match
+ }
+ } else { // exact command matching and...
+ if(p.fname != w.command) { // command does not match -
+ return 0; // exit and signal no match
+ }
+ }
+ }
+
+ if (w.args != "") { // If args is defined and...
+ if(w.exact == 0) { // pattern matching and...
+ if(!(p.args =~ w.args)) { // pattern does not match -
+ return 0; // exit and signal no match
+ }
+ } else { // exact args matching and...
+ if(p.args != w.args) { // args does not match -
+ return 0; // exit and signal no match
+ }
+ }
+ }
+
+ if (w.user != "") { // If user name is defined and...
+ ppw = getpwuid(p.uid); // Get user information for this process
+ if (ppw == 0) { // If unsuccessful...
+ return 0; // return no match
+ }
+ pw = *((passwd_t *) ppw);
+ if(w.exact == 0) { // pattern matching and...
+ if(!(pw.pw_name =~ w.user)) { // pattern does not match -
+ return 0; // exit and signal no match
+ }
+ } else { // exact user name matching and...
+ if(pw.pw_name != w.user) { // user name does not match -
+ return 0; // exit and signal no match
+ }
+ }
+ }
+
+ if ((w.pset != -1) && (p.bindpset != w.pset)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+class work_info_class_t {
+ int number; // Current workload
+ work_info_t w; // Data for current workload
+
+ work_info$() {
+ work_info_t wi[]; // Workload data dynamic array
+ int wc = 0; // Number of workloads
+ int firstmatch; // Set to use first workload that matches only
+ string fmstring;
+ proc_class_t pp; // Underlying process class data (snapshot)
+ proc_class_t ppzero; // Used to zero out by copying
+ double iv;
+ int i;
+ string wstring;
+ string wstr;
+ string dstr;
+ ulong pwstring;
+ ulong pwstr;
+ int initialized = 0;
+
+ if (initialized == 0) { // Initialize class
+ refresh$(pp); // Setup proc_class
+ fmstring = getenv("WORKLOAD_FIRSTMATCH"); // Load user defined matching policy
+ wstring = getenv("WORKLOAD_INFO"); // Load user defined data for matching
+
+ // Set matching policy
+ if (fmstring != nil) {
+ firstmatch = atoi(fmstring);
+ } else {
+ // Default to each process in one workload only
+ firstmatch = 1;
+ }
+
+ // Allocate memory for collecting totals
+ wi = new work_info_t[1];
+ wi[wc].name = "Total";
+ wi[wc].command = "";
+ wi[wc].args = "";
+ wi[wc].user = "";
+ wi[wc].pset = -1;
+
+ // Parse wstring into individual workloads
+ for (wstr = strtok_r(wstring, ";", &pwstring); wstr != nil; wstr = strtok_r(nil, ";", &pwstring)) {
+ // Allocate memory for this workload
+ wi = renew wi[++wc+1];
+ wi[wc].name = strtok_r(wstr, ",", &pwstr); // Get name
+ if (wi[wc].name == nil || wi[wc].name == " ") {
+ wi[wc].name = sprintf("Workload%d", wc);
+ }
+ wi[wc].command = strtok_r(nil, ",", &pwstr); // Get command
+ if (wi[wc].command == nil || wi[wc].command == " ") {
+ wi[wc].command = "";
+ }
+ wi[wc].args = strtok_r(nil, ",", &pwstr); // Get args
+ if (wi[wc].args == nil || wi[wc].args == " ") {
+ wi[wc].args = "";
+ }
+ wi[wc].user = strtok_r(nil, ",", &pwstr); // Get user
+ if (wi[wc].user == nil || wi[wc].user == " ") {
+ wi[wc].user = "";
+ }
+ dstr = strtok_r(nil, ",", &pwstr); // Get exact
+ if (dstr != nil) {
+ wi[wc].exact = atoi(dstr);
+ }
+ dstr = strtok_r(nil, ",", &pwstr); // Get cnt
+ if (dstr != nil) {
+ wi[wc].cnt = atoi(dstr);
+ }
+ dstr = strtok_r(nil, ",", &pwstr); // Get pset
+ if (dstr == nil || dstr == " ") {
+ wi[wc].pset = -1;
+ } else {
+ wi[wc].pset = atoi(dstr);
+ }
+ }
+
+#ifdef WORKINFO_PRINT
+ printf("\nWorkinfo class is initialized with the following data\n");
+ printf("Number of workloads = %d, firstmatch = %d (%s)\n",
+ wc, firstmatch, (firstmatch == 0 ? "Match all workloads" : "Match each process only once"));
+ for(i=1; i <= wc; i++) {
+ printf("Workload number %3d\n-------------------\n", i);
+ printf("name .................... %s\n", wi[i].name);
+ printf("command ................. %s\n", wi[i].command);
+ printf("args .................... %s\n", wi[i].args);
+ printf("user .................... %s\n", wi[i].user);
+ printf("exact ................... %d\n", wi[i].exact);
+ printf("pset .................... %d\n", wi[i].pset);
+ printf("Only count the number of\nprocesses and threads ... %s\n\n",
+ (wi[i].cnt == 0 ? "No" : "Yes"));
+ }
+#endif // WORKINFO_PRINT
+
+ number = -1;
+ initialized = 1;
+ return;
+ }
+
+ if (number != -1) { // Data is available
+ if (number < wc) {
+ w = wi[++number]; // Return next workload data
+ } else {
+ w = wi[0]; // Set w to Total data
+ number = -1; // Signal end of data
+ }
+ return;
+ }
+
+ for(i=0; i <= wc; i++) { // Reset counters
+ wi[i].count = 0;
+ wi[i].info = ppzero; // Not easy to use memset instead
+ }
+ refresh$(pp); // Get the snapshot
+ while (pp.index$ != -1) {
+ if (pp.termination != 0.0) {
+ continue; // Don't add in dead processes
+ }
+ for(i=0; i <= wc; i++) {
+ if (i == 0 || // Accumulate totals
+ (match_proc(pp, wi[i]) != 0)) {
+ wi[i].info.interval = pp.interval; // Take the last interval seen
+ iv = pp.interval;
+ if (iv == 0.0) { iv = 1.0; } // Safety net
+ if (pp.creation < wi[i].info.creation) { // Take the earliest creation
+ wi[i].info.creation = pp.creation;
+ }
+ if (wi[i].cnt == 0) {
+ // Track individual times
+ wi[i].info.lasttime = pp.lasttime;
+ wi[i].info.total_user += pp.total_user;
+ wi[i].info.total_system += pp.total_system;
+ wi[i].info.total_child += pp.total_child;
+ // Intervals vary, so accumulate here
+ wi[i].info.user_time += pp.user_time/iv;
+ wi[i].info.system_time += pp.system_time/iv;
+ wi[i].info.trap_time += pp.trap_time/iv;
+ wi[i].info.child_time += pp.child_time/iv;
+ wi[i].info.text_pf_time += pp.text_pf_time/iv;
+ wi[i].info.data_pf_time += pp.data_pf_time/iv;
+ wi[i].info.kernel_pf_time += pp.kernel_pf_time/iv;
+ wi[i].info.user_lock_time += pp.user_lock_time/iv;
+ wi[i].info.sleep_time += pp.sleep_time/iv;
+ wi[i].info.cpu_wait_time += pp.cpu_wait_time/iv;
+ wi[i].info.stoptime += pp.stoptime/iv;
+ wi[i].info.syscalls += pp.syscalls/iv;
+ wi[i].info.inblocks += pp.inblocks/iv;
+ wi[i].info.outblocks += pp.outblocks/iv;
+ // Next four are sizes not rates
+ wi[i].info.vmem_size += pp.vmem_size;
+ wi[i].info.rmem_size += pp.rmem_size;
+#ifdef XMAP
+ wi[i].info.pmem_size += pp.pmem_size;
+ wi[i].info.smem_size += pp.smem_size;
+#endif
+ wi[i].info.maj_faults += pp.maj_faults/iv;
+ wi[i].info.min_faults += pp.min_faults/iv;
+ wi[i].info.total_swaps += pp.total_swaps/iv;
+ wi[i].info.messages += pp.messages/iv;
+ wi[i].info.signals += pp.signals/iv;
+ wi[i].info.vcontexts += pp.vcontexts/iv;
+ wi[i].info.icontexts += pp.icontexts/iv;
+ wi[i].info.charios += pp.charios/iv;
+ // Divide these three by wi[i].count
+ wi[i].info.priority += pp.priority;
+ wi[i].info.niceness += pp.niceness;
+ }
+ wi[i].info.lwp_count += pp.lwp_count;
+ wi[i].count++;
+ if (firstmatch == 1 && i > 0) { // First match only counts
+ break;
+ }
+ }
+ }
+ refresh$(pp); // Next process
+ }
+ number = 0;
+ w = wi[number];
+ }
+};
+
+#endif
Added: trunk/orca/lib/SE/3.3/workinfo_class.se
==============================================================================
--- (empty file)
+++ trunk/orca/lib/SE/3.3/workinfo_class.se Mon Nov 1 14:00:49 2004
@@ -0,0 +1,341 @@
+#ifndef _WORKINFO_CLASS_SE_
+#define _WORKINFO_CLASS_SE_
+
+/***********************************************************
+* *
+* Workinfo class is based on Adrian's workload class *
+* *
+***********************************************************/
+
+/**************************************************************************
+Usage notes -
+This class is designed to collect process statistics for any group of
+processes defined by executed command, command arguments, executing user,
+and processor set binding.
+This class looks for WORKLOAD_INFO environment variable to initialize.
+
+To initialize workload information set WORKLOAD_INFO in the environment
+in the following way:
+WORKLOAD_INFO=name,command,args,user,exact,cnt,pset;...;...
+export WORKLOAD_INFO
+
+DO NOT use quotes ("") around string values (name,command,args,user).
+To skip one of the parameters use a SINGLE space. Missing or skipped
+parameters are ignored during process matching.
+Missing name defaults to WorkloadN, where N is workload number.
+Missing command, args, or user are skipped.
+By default pset is set to -1, cnt and exact are set to 0;
+
+Set pset to -1 to unset matching on processor set.
+Set exact to non-zero for exact matching, or 0 for pattern matching.
+Set cnt to non-zero to only count the number of processes and threads
+in a given workload. Other data is neither collected nor printed.
+
+If there is not enough process parameters defined in a set, workload
+parameters initialized in order with supplied data and the rest of the
+parameters are set to their default values.
+
+Set WORKLOAD_FIRSTMATCH=0 in the environment to match each process
+for all workloads.
+Set WORKLOAD_FIRSTMATCH=1 in the environment to match each process
+for one workload only.
+
+If WORKINFO_PRINT is defined, workload information is printed after
+initialization to allow for verification of workload data.
+
+Examples:
+export WORKLOAD_INFO='SE,se.sparc'
+Defines one workload with the name SE, command se.sparc, args and user
+empty string, exact 0 (match patterns), and no processor set.
+
+export WORKLOAD_INFO='SE,se.sparc, , ,1'
+The same as the above except matching is exact
+
+export WORKLOAD_INFO='SE,se.sparc;Ora, , ,oracle,1,1'
+Defines two workloads. In addition to SE workload, defines a workload named Ora
+that counts all processes owned by user oracle.
+
+Class usage example:
+########################################
+
+#include <workinfo_class.se>
+
+measure_workload()
+{
+ work_info_class_t ww;
+
+ ww.number = -1;
+#ifdef WORKLOAD_NO_TOTAL
+ refresh$(ww);
+#endif // WORKLOAD_NO_TOTAL
+ for (refresh$(ww); ww.number != -1; refresh$(ww)) {
+ printf("Wrkld=%s, number of procs=%d\n",ww.w.name,ww.w.count);
+ printf("Wrkld=%s, number of threads=%d\n",ww.w.name,ww.w.info.lwp_count);
+ // Get other data if not just counting processes
+ if (ww.w.cnt == 0) {
+ printf("Wrkld=%s, cpu_usr=%d\n",ww.w.name,100.0*ww.w.info.user_time);
+ printf("Wrkld=%s, cpu_sys=%d\n",ww.w.name,100.0*(ww.w.info.system_time+
+ ww.w.info.trap_time));
+ printf("Wrkld=%s, cpu_wait=%d\n",ww.w.name,100.0*ww.w.info.cpu_wait_time);
+ <...>
+ }
+ }
+<...>
+}
+########################################
+
+**************************************************************************/
+
+#include <unistd.se>
+#include <dirent.se>
+#include <fcntl.se>
+#include <proc.se>
+#include <process_class.se>
+#include <pwd.se>
+
+struct work_info_t {
+ string name; // Used by orcallator for header names for this workload
+ string command; // String to match against command name
+ string args; // String to match against command args
+ string user; // String to match against user name
+ int exact; // Set to match exact names instead of patterns
+ int cnt; // Set to count processes and threads only
+ int pset; // Processor set to match against
+ int count; // Number of processes that matched
+ proc_class_t info; // Use same data type to accumulate data
+};
+
+int match_proc(proc_class_t p, work_info_t w) {
+ passwd_t pw;
+ pointer_t ppw;
+
+ if (w.command != "") { // If command is defined and...
+ if(w.exact == 0) { // pattern matching and...
+ if(!(p.fname =~ w.command)) { // pattern does not match -
+ return 0; // exit and signal no match
+ }
+ } else { // exact command matching and...
+ if(p.fname != w.command) { // command does not match -
+ return 0; // exit and signal no match
+ }
+ }
+ }
+
+ if (w.args != "") { // If args is defined and...
+ if(w.exact == 0) { // pattern matching and...
+ if(!(p.args =~ w.args)) { // pattern does not match -
+ return 0; // exit and signal no match
+ }
+ } else { // exact args matching and...
+ if(p.args != w.args) { // args does not match -
+ return 0; // exit and signal no match
+ }
+ }
+ }
+
+ if (w.user != "") { // If user name is defined and...
+ ppw = getpwuid(p.uid); // Get user information for this process
+ if (ppw == 0) { // If unsuccessful...
+ return 0; // return no match
+ }
+ pw = *((passwd_t *) ppw);
+ if(w.exact == 0) { // pattern matching and...
+ if(!(pw.pw_name =~ w.user)) { // pattern does not match -
+ return 0; // exit and signal no match
+ }
+ } else { // exact user name matching and...
+ if(pw.pw_name != w.user) { // user name does not match -
+ return 0; // exit and signal no match
+ }
+ }
+ }
+
+ if ((w.pset != -1) && (p.bindpset != w.pset)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+class work_info_class_t {
+ int number; // Current workload
+ work_info_t w; // Data for current workload
+
+ work_info$() {
+ work_info_t wi[]; // Workload data dynamic array
+ int wc = 0; // Number of workloads
+ int firstmatch; // Set to use first workload that matches only
+ string fmstring;
+ proc_class_t pp; // Underlying process class data (snapshot)
+ proc_class_t ppzero; // Used to zero out by copying
+ double iv;
+ int i;
+ string wstring;
+ string wstr;
+ string dstr;
+ ulong pwstring;
+ ulong pwstr;
+ int initialized = 0;
+
+ if (initialized == 0) { // Initialize class
+ refresh$(pp); // Setup proc_class
+ fmstring = getenv("WORKLOAD_FIRSTMATCH"); // Load user defined matching policy
+ wstring = getenv("WORKLOAD_INFO"); // Load user defined data for matching
+
+ // Set matching policy
+ if (fmstring != nil) {
+ firstmatch = atoi(fmstring);
+ } else {
+ // Default to each process in one workload only
+ firstmatch = 1;
+ }
+
+ // Allocate memory for collecting totals
+ wi = new work_info_t[1];
+ wi[wc].name = "Total";
+ wi[wc].command = "";
+ wi[wc].args = "";
+ wi[wc].user = "";
+ wi[wc].pset = -1;
+
+ // Parse wstring into individual workloads
+ for (wstr = strtok_r(wstring, ";", &pwstring); wstr != nil; wstr = strtok_r(nil, ";", &pwstring)) {
+ // Allocate memory for this workload
+ wi = renew wi[++wc+1];
+ wi[wc].name = strtok_r(wstr, ",", &pwstr); // Get name
+ if (wi[wc].name == nil || wi[wc].name == " ") {
+ wi[wc].name = sprintf("Workload%d", wc);
+ }
+ wi[wc].command = strtok_r(nil, ",", &pwstr); // Get command
+ if (wi[wc].command == nil || wi[wc].command == " ") {
+ wi[wc].command = "";
+ }
+ wi[wc].args = strtok_r(nil, ",", &pwstr); // Get args
+ if (wi[wc].args == nil || wi[wc].args == " ") {
+ wi[wc].args = "";
+ }
+ wi[wc].user = strtok_r(nil, ",", &pwstr); // Get user
+ if (wi[wc].user == nil || wi[wc].user == " ") {
+ wi[wc].user = "";
+ }
+ dstr = strtok_r(nil, ",", &pwstr); // Get exact
+ if (dstr != nil) {
+ wi[wc].exact = atoi(dstr);
+ }
+ dstr = strtok_r(nil, ",", &pwstr); // Get cnt
+ if (dstr != nil) {
+ wi[wc].cnt = atoi(dstr);
+ }
+ dstr = strtok_r(nil, ",", &pwstr); // Get pset
+ if (dstr == nil || dstr == " ") {
+ wi[wc].pset = -1;
+ } else {
+ wi[wc].pset = atoi(dstr);
+ }
+ }
+
+#ifdef WORKINFO_PRINT
+ printf("\nWorkinfo class is initialized with the following data\n");
+ printf("Number of workloads = %d, firstmatch = %d (%s)\n",
+ wc, firstmatch, (firstmatch == 0 ? "Match all workloads" : "Match each process only once"));
+ for(i=1; i <= wc; i++) {
+ printf("Workload number %3d\n-------------------\n", i);
+ printf("name .................... %s\n", wi[i].name);
+ printf("command ................. %s\n", wi[i].command);
+ printf("args .................... %s\n", wi[i].args);
+ printf("user .................... %s\n", wi[i].user);
+ printf("exact ................... %d\n", wi[i].exact);
+ printf("pset .................... %d\n", wi[i].pset);
+ printf("Only count the number of\nprocesses and threads ... %s\n\n",
+ (wi[i].cnt == 0 ? "No" : "Yes"));
+ }
+#endif // WORKINFO_PRINT
+
+ number = -1;
+ initialized = 1;
+ return;
+ }
+
+ if (number != -1) { // Data is available
+ if (number < wc) {
+ w = wi[++number]; // Return next workload data
+ } else {
+ w = wi[0]; // Set w to Total data
+ number = -1; // Signal end of data
+ }
+ return;
+ }
+
+ for(i=0; i <= wc; i++) { // Reset counters
+ wi[i].count = 0;
+ wi[i].info = ppzero; // Not easy to use memset instead
+ }
+ refresh$(pp); // Get the snapshot
+ while (pp.index$ != -1) {
+ if (pp.termination != 0.0) {
+ continue; // Don't add in dead processes
+ }
+ for(i=0; i <= wc; i++) {
+ if (i == 0 || // Accumulate totals
+ (match_proc(pp, wi[i]) != 0)) {
+ wi[i].info.interval = pp.interval; // Take the last interval seen
+ iv = pp.interval;
+ if (iv == 0.0) { iv = 1.0; } // Safety net
+ if (pp.creation < wi[i].info.creation) { // Take the earliest creation
+ wi[i].info.creation = pp.creation;
+ }
+ if (wi[i].cnt == 0) {
+ // Track individual times
+ wi[i].info.lasttime = pp.lasttime;
+ wi[i].info.total_user += pp.total_user;
+ wi[i].info.total_system += pp.total_system;
+ wi[i].info.total_child += pp.total_child;
+ // Intervals vary, so accumulate here
+ wi[i].info.user_time += pp.user_time/iv;
+ wi[i].info.system_time += pp.system_time/iv;
+ wi[i].info.trap_time += pp.trap_time/iv;
+ wi[i].info.child_time += pp.child_time/iv;
+ wi[i].info.text_pf_time += pp.text_pf_time/iv;
+ wi[i].info.data_pf_time += pp.data_pf_time/iv;
+ wi[i].info.kernel_pf_time += pp.kernel_pf_time/iv;
+ wi[i].info.user_lock_time += pp.user_lock_time/iv;
+ wi[i].info.sleep_time += pp.sleep_time/iv;
+ wi[i].info.cpu_wait_time += pp.cpu_wait_time/iv;
+ wi[i].info.stoptime += pp.stoptime/iv;
+ wi[i].info.syscalls += pp.syscalls/iv;
+ wi[i].info.inblocks += pp.inblocks/iv;
+ wi[i].info.outblocks += pp.outblocks/iv;
+ // Next four are sizes not rates
+ wi[i].info.vmem_size += pp.vmem_size;
+ wi[i].info.rmem_size += pp.rmem_size;
+#ifdef XMAP
+ wi[i].info.pmem_size += pp.pmem_size;
+ wi[i].info.smem_size += pp.smem_size;
+#endif
+ wi[i].info.maj_faults += pp.maj_faults/iv;
+ wi[i].info.min_faults += pp.min_faults/iv;
+ wi[i].info.total_swaps += pp.total_swaps/iv;
+ wi[i].info.messages += pp.messages/iv;
+ wi[i].info.signals += pp.signals/iv;
+ wi[i].info.vcontexts += pp.vcontexts/iv;
+ wi[i].info.icontexts += pp.icontexts/iv;
+ wi[i].info.charios += pp.charios/iv;
+ // Divide these three by wi[i].count
+ wi[i].info.priority += pp.priority;
+ wi[i].info.niceness += pp.niceness;
+ }
+ wi[i].info.lwp_count += pp.lwp_count;
+ wi[i].count++;
+ if (firstmatch == 1 && i > 0) { // First match only counts
+ break;
+ }
+ }
+ }
+ refresh$(pp); // Next process
+ }
+ number = 0;
+ w = wi[number];
+ }
+};
+
+#endif
More information about the Orca-checkins
mailing list