|
|
/*
* Title: analog.h - header file for log analyzer * * Description: This file provides structures and macros for log analyzer. * * Types: * PoolLogRec Poolsnap structure * MemLogRec Memsnap structure * LogType Enumeration of known log types * * Macros: * * GET_DELTA Computes the difference between first & last entry * GREATER_LESS_OR_EQUAL Increments trend if cur>prv, decrements if cur<prv * PRINT_IF_TREND Prints definite or probable leaks based on trend * MAX Returns the larger value * * Copyright (c) 1998 Microsoft Corporation * * Revision history: LarsOp (created) 12/8/98 * */
//
// Structure for poolsnap logs
//
typedef struct _PoolLogRec { char Name[32]; char Type[32]; long Allocs; long Frees; long Diff; long Bytes; long PerAlloc; } PoolLogRec;
//
// Structure for memsnap logs
//
typedef struct _MemLogRec { DWORD Pid; char Name[64]; long WorkingSet; long PagedPool; long NonPagedPool; long PageFile; long Commit; long Handles; long Threads; } MemLogRec;
//
// Enumeration of the known log types
//
typedef enum { MEM_LOG=0, // must be zero (see LogTypeLabels)
POOL_LOG, // must be 1 (see LogTypeLabels)
UNKNOWN_LOG_TYPE } LogType;
//
// Array of labels to simplify printing the enumerated type
//
char *LogTypeLabels[]={"MemSnap", "PoolSnap", "Unknown"};
//
// Arbitrary buffer length
//
#define BUF_LEN 256
#define PERCENT_TO_PRINT 10
//
// GET_DELTA simply records the difference (end-begin) for specified field
//
// Args:
// delta - record to receive result values
// ptr - array of records (used to compare first and last)
// max - number of entries in the array
// field - field name to compute
//
// Returns: nothing (treat like void function)
//
#define GET_DELTA(delta, ptr, max, field) delta.field = ptr[max-1].field - ptr[0].field
//
// GREATER_LESS_OR_EQUAL calculates TrendInfo.
//
// Args:
// trend - record containing running tally
// ptr - array of records (used to compare curr and prev)
// i - index of current entry in the array
// field - field name to compare
//
// Returns: nothing (treat like void function)
//
// TrendInfo is a running tally of the periods a value went up vs.
// the periods it went down. See macro in analog.h
//
// if (curval>oldval) {
// trend++;
// } else if (curval<oldval) {
// trend--;
// } else {
// trend=trend; // stay same
// }
//
#define GREATER_LESS_OR_EQUAL(trend, ptr, i, field) \
if (ptr[i].field - ptr[i-1].field) \ trend.field += (((ptr[i].field - ptr[i-1].field) > 0) ? 1 : -1);
//
// MAX returns the larger value of the two
//
// Args: x,y: arguments of the same type where '>' is defined.
//
// Returns: the larger value
//
#define MAX(x, y) (x>y?x:y)
//
// PERCENT returns the percentage
//
// Args:
// delta - value of increase
// base - initial value
//
// Returns: the percent if base!=0, else 0
//
#define PERCENT(delta, base) (base!=0?(100*delta)/base:0)
#define VAL_AND_PERCENT(delta, ptr, field) delta.field, PERCENT(delta.field, ptr[0].field)
//
// PRINT_IF_TREND reports probable or definite leaks for any field.
//
// Args:
// ptr - array of records (used to display first and last)
// trend - record containing running tally
// delta - record containing raw differences of first and last
// max - number of entries in the array
// field - field name to compare
//
// Returns: nothing (treat like void function)
//
// Definite leak is where the value goes up every period
// Probable leak is where the value goes up most of the time
//
//
// PRINT_HEADER and PRINT_IF_TREND must agree on field widths.
//
#define PRINT_HEADER() { \
TableHeader(); \ if( bHtmlStyle ) { \ TableStart(); \ printf("<TH COLSPAN=2> %s </TH>\n",g_pszComputerName); \ printf("<TH COLSPAN=6>\n"); \ if( g_fShowExtraInfo ) { \ printf("BuildNumber=%s\n",g_pszBuildNumber); \ printf("<BR>BuildType=%s\n",g_pszBuildType); \ printf("<BR>Last SystemTime=%s\n",g_pszSystemTime); \ printf("<BR>%s\n",g_pszComments); \ } \ printf("</TH>\n"); \ TableEnd(); \ } \ TableStart(); \ TableField("%-15s", "Name" ); \ TableField("%-12s", "Probability"); \ TableField("%-12s", "Object" ); \ TableField("%10s", "Change" ); \ TableField("%10s", "Start" ); \ TableField("%10s", "End" ); \ TableField("%8s", "Percent"); \ TableField("%10s", "Rate/hour" ); \ TableEnd(); }
#define PRINT_TRAILER() { \
TableTrailer(); }
#define PRINT_IF_TREND(ptr, trend, delta, max, field) \
if (trend.field >= max/2) { \ BOOL bDefinite= (trend.field==max-1) ? 1 : 0; \ if( bDefinite || (g_ReportLevel>0) ) { \ TableStart(); \ TableField("%-15s", ptr[0].Name); \ TableField("%-12s", bDefinite ? "Definite" : "Probable"); \ TableField("%-12s", #field); \ TableNum("%10ld", delta.field); \ TableNum("%10ld", ptr[0].field); \ TableNum("%10ld", ptr[max-1].field); \ TableNum("%8ld", PERCENT(delta.field,ptr[0].field)); \ if( g_dwElapseTickCount ) { \ TableNum("%10d",Trick( delta.field ,g_dwElapseTickCount) ); \ } else { \ TableField("%-10s"," "); \ }; \ TableEnd(); \ } \ }
#define ANY_PERCENT_GREATER(delta, ptr) (\
(PERCENT(delta.WorkingSet , ptr[0].WorkingSet ) > PERCENT_TO_PRINT) || \ (PERCENT(delta.PagedPool , ptr[0].PagedPool ) > PERCENT_TO_PRINT) || \ (PERCENT(delta.NonPagedPool , ptr[0].NonPagedPool) > PERCENT_TO_PRINT) || \ (PERCENT(delta.PageFile , ptr[0].PageFile ) > PERCENT_TO_PRINT) || \ (PERCENT(delta.Commit , ptr[0].Commit ) > PERCENT_TO_PRINT) || \ (PERCENT(delta.Handles , ptr[0].Handles ) > PERCENT_TO_PRINT) || \ (PERCENT(delta.Threads , ptr[0].Threads ) > PERCENT_TO_PRINT))
|