212 lines
7.3 KiB
C
212 lines
7.3 KiB
C
|
/*
|
||
|
* 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))
|