#include <w.h> #include <w_statistics.h> class w_statistics_t { // members of interest to users w_statistics_t *copy_brief() const; w_statistics_t *copy_all() const; int *int_val(NAMED_CONSTANT) const; static int error_int; //returned if error uint *uint_val(NAMED_CONSTANT) const; static unsigned int error_int; //returned if error float *float_val(NAMED_CONSTANT) const; static float error_float; //returned if error char typechar(NAMED_CONSTANT) const; //returns 'v' for unsigned long // 'l' for long // 'i' for int // 'u' for unsigned int // 'f' for float const char *string(NAMED_CONSTANT) const; const char *module(NAMED_CONSTANT) const; // for arithmetic friend w_statistics_t & operator+=(w_statistics_t &, const w_statistics_t &); friend w_statistics_t & operator-=(w_statistics_t &, const w_statistics_t &); void zero(); // clears all stats }; // For SDL users static shrc Shore::gather_stats(w_statistics_t &, bool remote=false);
This is a class for collecting and printing simple statistics, meaning integers, unsigned integers, and one-word floating-point numbers. Statistics are collected in modules (meant to correspond to software modules). Each module consists of a list of statistics, along with metadata describing the type and semantics of each statistic. Modules are distinguished by unique masks, which are manifest constants. (There is no convenient way to make sure the masks are unique.)
In order to reduce the effort required
to read this manual page, we distinguish
two kinds of readers:
those writing software that generates statistics
(e.g., a value-added-server),
and those writing software that uses statistics
generated elsewhere (e.g., an application that
uses statistics generated by the Shore Object Cache).
After reading the section below,
MECHANISM
This class allows local and remote statistics to be collected. In the local case, the modules in an instance of w_statistics_t store references to data structures that are updated in place by the software module that generates the statistics. For example, Object Cache statistics are generated by the Object Cache, and are stored in a data structure to which the application's w_statistics_t instance has direct access through a const reference.
In the remote case, copies of the statistics and all their metadata are put in the w_statistics_t instance. The implications of this are that it can be confusing to copy and save statistics, because local (static) statistics and remote (malloc-ed) statistics have to be treated differently.
In Shore, we use a Perl script (in
the source tree under
tools/stats.pl,
)
to generate the statistics modules for the
various software modules.
The section
GENERATING MODULES
Any number of software modules can `add' their statistics to a w_statistics_t instance for later printing by an application. The application can use generic methods to print the entire set of modules, or it can print only selected statistics according to its own formatting rules, or use selected statistics for its own purposes.
We use an (abbreviated) example from the Shore source tree to show how to use the Perls script stats.pl to generate statistics modules. The input to the Perl script is as follows:
SM Storage manager = 0x00060000 sm_stats_info_t { // Record pinning: u_long rec_pin_cnt Times records were pinned in the buffer pool u_long rec_unpin_cnt Times records were unpinned // Btree stats: u_long bt_find_cnt Btree lookups (find_assoc()) u_long bt_insert_cnt Btree inserts (create_assoc) u_long bt_remove_cnt Btree removes (destroy_assoc) u_long bt_scan_cnt Btree scans started // ... we don't include all the stats };
The first line identifies the module and some of the metadata to be associated with it. SM is a character string that will be a prefix for all the manifest constants generated by the script. What lies between SM and the equal sign (=) becomes a descriptive string for the module, for the purpose of printing the statistics. 0x00060000 is for distinguishing this module from others. sm_stats_info_t is the name of a C++ class that "owns" the statistics. This name is used to generate the file names for the output of stats.pl. The files generated in this example are:
sm_stats_info_t_def.i sm_stats_info_t_msg.i sm_stats_info_t_op.i sm_stats_info_t_struct.i
The second line is a comment. C++ and C comments, and blank lines are acceptable.
The next lines defines a single statistic, whose type is u_long. Types can be any one of : long, u_long, int, u_int, float. After the type is a C/C++ struct member name. The class sm_stats_info_t will contain the members
unsigned long rec_pin_cnt; unsigned long rec_unpin_cnt;and so on. The list of members is generated by the script, and will be found in sm_stats_info_t_struct.i. The script does not generate the entire definition for sm_stats_info_t because the author of the software may wish to make the statistics be only a small part of the class, and therefore define the class as follows:
class sm_stats_info_t { ... // stuff #include "sm_stats_info_t_struct.i" ... // more stuff };
Getting back to the input to the Perl script, the remainder of the third line is a string that describes the semantics of the statistic. It will be quoted by the Perl script. You should not quote it in your input file. The string should not be very long because it makes the output difficult to format nicely.
The file sm_stats_info_t_op.i contains the definition of an output operator
w_statistics_t & operator<<(w_statistics_t &s,const sm_stats_info_t &t);This operator is declared to be a friend of your class sm_stats_info_t (by including sm_stats_info_t_struct.i
The file sm_stats_info_t_msg.i contains the list of descriptive strings for the module. These must be used as follows (sorry, this isn't automatically generated): in some single place (so it isn't multiply defined), do
// the strings: const char *sm_stats_info_t ::stat_names[] = { #include "sm_stats_info_t_msg.i" };
The output file sm_stats_info_t_def.i contains the manifest constants for the module, which are generated for (optional) use by the application (the program that prints the statistics).
Using the above example, the module of statistics called a sm_stats_info_t is added to a w_statistics_t instance with the operator
w_statistics_t & operator<<(w_statistics_t &s,const sm_stats_info_t &t)as follows:
w_statistics_t stats; // assume the sm_stats_info_t is called ss_m::stats_info stats << ss_m::stats_info;
Copy_brief makes copies of the statistics, but copies pointers to the metadata. The result is mutable.
Copy_all makes copies of the statistics and the metadata. The result is mutable.
The methods int_val uint_val, and float_val return the integer, unsigned integer, or floating point value of the statistic. When an error occurs in evaluating the method, these functions return error_int, error_uint, and error_float, respectively. You can find out the type of a statistic with the method typechar, which returns 'v' for unsigned longs, 'l' for longs, 'i' for ints, 'u' for unsigned ints, and 'f' for floats.
String returns the printable, descriptive string for the statistic indicated by the manifest (named) constant. Module returns the printable, descriptive string for the module of which the statistic is a member.
Operators operator+= and operator-= perform the indicated arithmetic on the corresponding statistics in the operands, which are instances of w_statistics_t. The operands must contain exactly the same statistics, and left-hand operand must be mutable, which means that it must be a copy of a local (static) instance, or it must be a remote (malloced) instance.
Zero sets all the values to 0 (or 0.0 for floats). It will fail on an immutable (static, local) instance.
Applications (users of SDL) will use the method Shore::gather_stats.
w_statistics_t localstats; SH_DO(Shore::gather_stats(localstats)); w_statistics_t remotestats; SH_DO(Shore::gather_stats(remotestats, true));
A program can use the output operator ostream & operator<<(ostream &out, const w_statistics_t &s) to print all the statistics in an instance of the class w_statistics_t. The program does not need to have any compiled-in knowledge of any of the modules contained in the instance.
This operator does not print any information about statistics whose values are zero.
w_statistics_t stats; .. cout << stats << endl;
In order to use selected statistics, a program must have compiled in the manifest constants for the modules of interest. For SDL users, these are included by #include <ShoreStats.h> See the following man pages for lists of the constants available for the various software layers: statistics(oc) , statistics(svas) , and statistics(ssm) .
For example, to print the storage manager's count of the bytes of log generated:
w_statistics_t current; SH_DO(Shore::gather_stats(current, true)); cout << "Module " << current.module(SM_log_bytes_generated) << endl; cout << ::form("\t%-30.30s %10.10d", current.string(SM_log_bytes_generated), current.int_val(SM_log_bytes_generated)) << endl;The first print statement prints the name of the module; you can call the method w_statistics_t::module with the manifest constant for any statistic to get a descriptive name of the module (in this case, "Storage manager"). The second print statement formats the output as follows:
Bytes written to the log 0000000928
Statistics can be saved for later use in computing the costs of certain operations. The natural thing to want to do is to gather two entirely different copies of all the statistics, you can just gather twice, and compute the difference:
w_statistics_t earlier; SH_DO(Shore::gather_stats(earlier, true)); .. w_statistics_t later; SH_DO(Shore::gather_stats(later, true)); // DON'T DO THIS WITH LOCAL STATISICS later -= earlier; cout << later << endl;
This will not work for local statistics because the differences will always be zero! Each of the instances of w_statistics_t points directly to the current local statistics data structures for each module! It works fine for remote statistics (those gathered from the Shore server) because each of earlier and later is a complete copy of the statistics and metadata.
To save local statistics, you need to make a copy.
w_statistics_t current; SH_DO(Shore::gather_stats(current)); w_statistics_t *saved = current.copy_brief();Copy_brief copies only that values of the statistics, and it makes duplicate references to the metadata stored in current (rather than copying all the descriptive strings, for example). IMPORTANT: This means that you had better not let current go out of scope until you are finished with saved ! Now, you'd like to just subtract one from the other:
// ERROR: current -= *saved;but that doesn't work because current is immutable. (Remember, it points into the current statistics.) You have to copy it also:
// OK: w_statistics_t *cur = current.copy_brief(); *cur -= saved; cout << *cur << endl; // Don't forget to delete: delete cur; delete saved;
With remote statistics, you might wonder how you can save the expense of twice copying all the metadata from the server. Here's how:
w_statistics_t current; w_statistics_t *saved; SH_DO(Shore::gather_stats(current, true)); w_statistics_t *saved = current.copy_brief(); .. // gather a current set SH_DO(Shore::gather_stats(current, true)); current -= *saved; cout << current << endl;
In this example, because current contains remote statistics (everything is malloced), it is a writable instance of w_statistics_t; it can be overwritten and updated by the subtraction.VERSION
This manual page applies to Version 1.0 of theShore software.SPONSORSHIP
The Shore project is sponsored by the Advanced Research Project Agency, ARPA order number 018 (formerly 8230), monitored by the U.S. Army Research Laboratory under contract DAAB07-92-C-Q508.COPYRIGHT
Copyright (c) 1994, 1995, 1996 Computer Sciences Department, University of Wisconsin -- Madison. All Rights Reserved.SEE ALSO
rc(fc) , intro(fc) , statistics(oc) , statistics(svas) , and statistics(ssm) .