?? proflfun.c
字號:
/*******************************************************/ /* "C" Language Integrated Production System */ /* */ /* CLIPS Version 6.24 06/02/06 */ /* */ /* CONSTRUCT PROFILING FUNCTIONS MODULE */ /*******************************************************//*************************************************************//* Purpose: Contains the code for profiling the amount of *//* time spent in constructs and user defined functions. *//* *//* Principal Programmer(s): *//* Gary D. Riley *//* *//* Contributing Programmer(s): *//* *//* Revision History: *//* 6.23: Modified OutputProfileInfo to allow a before *//* and after prefix so that a string buffer does *//* not need to be created to contain the entire *//* prefix. This allows a buffer overflow problem *//* to be corrected. DR0857. *//* *//* 6.24: Renamed BOOLEAN macro type to intBool. *//* *//* Added pragmas to remove compilation warnings. *//* *//* Corrected code to remove run-time program *//* compiler warnings. *//* *//*************************************************************/#define _PROFLFUN_SOURCE_#include "setup.h"#if PROFILING_FUNCTIONS#include "argacces.h"#include "classcom.h"#include "dffnxfun.h"#include "envrnmnt.h"#include "extnfunc.h"#include "genrccom.h"#include "genrcfun.h"#include "memalloc.h"#include "msgcom.h"#include "router.h"#include "sysdep.h"#include "proflfun.h"#include <string.h>#define NO_PROFILE 0#define USER_FUNCTIONS 1#define CONSTRUCTS_CODE 2#define OUTPUT_STRING "%-40s %7ld %15.6f %8.2f%% %15.6f %8.2f%%\n"/***************************************//* LOCAL INTERNAL FUNCTION DEFINITIONS *//***************************************/ static intBool OutputProfileInfo(void *,char *,struct constructProfileInfo *, char *,char *,char *,char **); static void OutputUserFunctionsInfo(void *); static void OutputConstructsCodeInfo(void *);#if (! RUN_TIME) static void ProfileClearFunction(void *);#endif/******************************************************//* ConstructProfilingFunctionDefinitions: Initializes *//* the construct profiling functions. *//******************************************************/globle void ConstructProfilingFunctionDefinitions( void *theEnv) { struct userDataRecord profileDataInfo = { 0, CreateProfileData, DeleteProfileData }; AllocateEnvironmentData(theEnv,PROFLFUN_DATA,sizeof(struct profileFunctionData),NULL); memcpy(&ProfileFunctionData(theEnv)->ProfileDataInfo,&profileDataInfo,sizeof(struct userDataRecord)); ProfileFunctionData(theEnv)->LastProfileInfo = NO_PROFILE; ProfileFunctionData(theEnv)->PercentThreshold = 0.0; ProfileFunctionData(theEnv)->OutputString = OUTPUT_STRING;#if ! RUN_TIME EnvDefineFunction2(theEnv,"profile",'v', PTIEF ProfileCommand,"ProfileCommand","11w"); EnvDefineFunction2(theEnv,"profile-info",'v', PTIEF ProfileInfoCommand,"ProfileInfoCommand","01w"); EnvDefineFunction2(theEnv,"profile-reset",'v', PTIEF ProfileResetCommand,"ProfileResetCommand","00"); EnvDefineFunction2(theEnv,"set-profile-percent-threshold",'d', PTIEF SetProfilePercentThresholdCommand, "SetProfilePercentThresholdCommand","11n"); EnvDefineFunction2(theEnv,"get-profile-percent-threshold",'d', PTIEF GetProfilePercentThresholdCommand, "GetProfilePercentThresholdCommand","00"); ProfileFunctionData(theEnv)->ProfileDataID = InstallUserDataRecord(theEnv,&ProfileFunctionData(theEnv)->ProfileDataInfo); EnvAddClearFunction(theEnv,"profile",ProfileClearFunction,0);#endif }/**********************************//* CreateProfileData: Allocates a *//* profile user data structure. *//**********************************/globle void *CreateProfileData( void *theEnv) { struct constructProfileInfo *theInfo; theInfo = (struct constructProfileInfo *) genalloc(theEnv,sizeof(struct constructProfileInfo)); theInfo->numberOfEntries = 0; theInfo->childCall = FALSE; theInfo->startTime = 0.0; theInfo->totalSelfTime = 0.0; theInfo->totalWithChildrenTime = 0.0; return(theInfo); } /**************************************//* DeleteProfileData: *//**************************************/globle void DeleteProfileData( void *theEnv, void *theData) { genfree(theEnv,theData,sizeof(struct constructProfileInfo)); }/**************************************//* ProfileCommand: H/L access routine *//* for the profile command. *//**************************************/globle void ProfileCommand( void *theEnv) { char *argument; DATA_OBJECT theValue; if (EnvArgCountCheck(theEnv,"profile",EXACTLY,1) == -1) return; if (EnvArgTypeCheck(theEnv,"profile",1,SYMBOL,&theValue) == FALSE) return; argument = DOToString(theValue); if (! Profile(theEnv,argument)) { ExpectedTypeError1(theEnv,"profile",1,"symbol with value constructs, user-functions, or off"); return; } return; }/******************************//* Profile: C access routine *//* for the profile command. *//******************************/globle intBool Profile( void *theEnv, char *argument) { /*======================================================*/ /* If the argument is the symbol "user-functions", then */ /* user-defined functions should be profiled. If the */ /* argument is the symbol "constructs", then */ /* deffunctions, generic functions, message-handlers, */ /* and rule RHS actions are profiled. */ /*======================================================*/ if (strcmp(argument,"user-functions") == 0) { ProfileFunctionData(theEnv)->ProfileStartTime = gentime(); ProfileFunctionData(theEnv)->ProfileUserFunctions = TRUE; ProfileFunctionData(theEnv)->ProfileConstructs = FALSE; ProfileFunctionData(theEnv)->LastProfileInfo = USER_FUNCTIONS; } else if (strcmp(argument,"constructs") == 0) { ProfileFunctionData(theEnv)->ProfileStartTime = gentime(); ProfileFunctionData(theEnv)->ProfileUserFunctions = FALSE; ProfileFunctionData(theEnv)->ProfileConstructs = TRUE; ProfileFunctionData(theEnv)->LastProfileInfo = CONSTRUCTS_CODE; } /*======================================================*/ /* Otherwise, if the argument is the symbol "off", then */ /* don't profile constructs and user-defined functions. */ /*======================================================*/ else if (strcmp(argument,"off") == 0) { ProfileFunctionData(theEnv)->ProfileEndTime = gentime(); ProfileFunctionData(theEnv)->ProfileTotalTime += (ProfileFunctionData(theEnv)->ProfileEndTime - ProfileFunctionData(theEnv)->ProfileStartTime); ProfileFunctionData(theEnv)->ProfileUserFunctions = FALSE; ProfileFunctionData(theEnv)->ProfileConstructs = FALSE; } /*=====================================================*/ /* Otherwise, generate an error since the only allowed */ /* arguments are "on" or "off." */ /*=====================================================*/ else { return(FALSE); } return(TRUE); }/******************************************//* ProfileInfoCommand: H/L access routine *//* for the profile-info command. *//******************************************/globle void ProfileInfoCommand( void *theEnv) { int argCount; DATA_OBJECT theValue; char buffer[512]; /*===================================*/ /* The profile-info command expects */ /* at most a single symbol argument. */ /*===================================*/ if ((argCount = EnvArgCountCheck(theEnv,"profile",NO_MORE_THAN,1)) == -1) return; /*===========================================*/ /* The first profile-info argument indicates */ /* the field on which sorting is performed. */ /*===========================================*/ if (argCount == 1) { if (EnvArgTypeCheck(theEnv,"profile",1,SYMBOL,&theValue) == FALSE) return; } /*==================================*/ /* If code is still being profiled, */ /* update the profile end time. */ /*==================================*/ if (ProfileFunctionData(theEnv)->ProfileUserFunctions || ProfileFunctionData(theEnv)->ProfileConstructs) { ProfileFunctionData(theEnv)->ProfileEndTime = gentime(); ProfileFunctionData(theEnv)->ProfileTotalTime += (ProfileFunctionData(theEnv)->ProfileEndTime - ProfileFunctionData(theEnv)->ProfileStartTime); } /*==================================*/ /* Print the profiling information. */ /*==================================*/ if (ProfileFunctionData(theEnv)->LastProfileInfo != NO_PROFILE) { gensprintf(buffer,"Profile elapsed time = %g seconds\n", ProfileFunctionData(theEnv)->ProfileTotalTime); EnvPrintRouter(theEnv,WDISPLAY,buffer); if (ProfileFunctionData(theEnv)->LastProfileInfo == USER_FUNCTIONS) { EnvPrintRouter(theEnv,WDISPLAY,"Function Name "); } else if (ProfileFunctionData(theEnv)->LastProfileInfo == CONSTRUCTS_CODE) { EnvPrintRouter(theEnv,WDISPLAY,"Construct Name "); } EnvPrintRouter(theEnv,WDISPLAY,"Entries Time % Time+Kids %+Kids\n"); if (ProfileFunctionData(theEnv)->LastProfileInfo == USER_FUNCTIONS) { EnvPrintRouter(theEnv,WDISPLAY,"------------- "); } else if (ProfileFunctionData(theEnv)->LastProfileInfo == CONSTRUCTS_CODE) { EnvPrintRouter(theEnv,WDISPLAY,"-------------- "); } EnvPrintRouter(theEnv,WDISPLAY,"------- ------ ----- --------- ------\n"); } if (ProfileFunctionData(theEnv)->LastProfileInfo == USER_FUNCTIONS) OutputUserFunctionsInfo(theEnv); if (ProfileFunctionData(theEnv)->LastProfileInfo == CONSTRUCTS_CODE) OutputConstructsCodeInfo(theEnv); }/**********************************************//* StartProfile: Initiates bookkeeping needed *//* to profile a construct or function. *//**********************************************/globle void StartProfile( void *theEnv, struct profileFrameInfo *theFrame, struct userData **theList, intBool checkFlag) { double startTime, addTime; struct constructProfileInfo *profileInfo; if (! checkFlag) { theFrame->profileOnExit = FALSE; return; } profileInfo = (struct constructProfileInfo *) FetchUserData(theEnv,ProfileFunctionData(theEnv)->ProfileDataID,theList); theFrame->profileOnExit = TRUE; theFrame->parentCall = FALSE; startTime = gentime(); theFrame->oldProfileFrame = ProfileFunctionData(theEnv)->ActiveProfileFrame; if (ProfileFunctionData(theEnv)->ActiveProfileFrame != NULL) { addTime = startTime - ProfileFunctionData(theEnv)->ActiveProfileFrame->startTime; ProfileFunctionData(theEnv)->ActiveProfileFrame->totalSelfTime += addTime; } ProfileFunctionData(theEnv)->ActiveProfileFrame = profileInfo; ProfileFunctionData(theEnv)->ActiveProfileFrame->numberOfEntries++; ProfileFunctionData(theEnv)->ActiveProfileFrame->startTime = startTime; if (! ProfileFunctionData(theEnv)->ActiveProfileFrame->childCall) { theFrame->parentCall = TRUE; theFrame->parentStartTime = startTime; ProfileFunctionData(theEnv)->ActiveProfileFrame->childCall = TRUE; } }/*******************************************//* EndProfile: Finishes bookkeeping needed *//* to profile a construct or function. *//*******************************************/globle void EndProfile( void *theEnv, struct profileFrameInfo *theFrame) { double endTime, addTime; if (! theFrame->profileOnExit) return; endTime = gentime(); if (theFrame->parentCall) { addTime = endTime - theFrame->parentStartTime; ProfileFunctionData(theEnv)->ActiveProfileFrame->totalWithChildrenTime += addTime; ProfileFunctionData(theEnv)->ActiveProfileFrame->childCall = FALSE; } ProfileFunctionData(theEnv)->ActiveProfileFrame->totalSelfTime += (endTime - ProfileFunctionData(theEnv)->ActiveProfileFrame->startTime); if (theFrame->oldProfileFrame != NULL) { theFrame->oldProfileFrame->startTime = endTime; } ProfileFunctionData(theEnv)->ActiveProfileFrame = theFrame->oldProfileFrame; }/******************************************//* OutputProfileInfo: Prints out a single *//* line of profile information. *//******************************************/static intBool OutputProfileInfo( void *theEnv, char *itemName, struct constructProfileInfo *profileInfo, char *printPrefixBefore, char *printPrefix, char *printPrefixAfter, char **banner) { double percent = 0.0, percentWithKids = 0.0; char buffer[512]; if (profileInfo == NULL) return(FALSE); if (profileInfo->numberOfEntries == 0) return(FALSE); if (ProfileFunctionData(theEnv)->ProfileTotalTime != 0.0) { percent = (profileInfo->totalSelfTime * 100.0) / ProfileFunctionData(theEnv)->ProfileTotalTime; if (percent < 0.005) percent = 0.0; percentWithKids = (profileInfo->totalWithChildrenTime * 100.0) / ProfileFunctionData(theEnv)->ProfileTotalTime; if (percentWithKids < 0.005) percentWithKids = 0.0; } if (percent < ProfileFunctionData(theEnv)->PercentThreshold) return(FALSE); if ((banner != NULL) && (*banner != NULL)) { EnvPrintRouter(theEnv,WDISPLAY,*banner); *banner = NULL; } if (printPrefixBefore != NULL) { EnvPrintRouter(theEnv,WDISPLAY,printPrefixBefore); } if (printPrefix != NULL) { EnvPrintRouter(theEnv,WDISPLAY,printPrefix); } if (printPrefixAfter != NULL) { EnvPrintRouter(theEnv,WDISPLAY,printPrefixAfter); } if (strlen(itemName) >= 40) { EnvPrintRouter(theEnv,WDISPLAY,itemName); EnvPrintRouter(theEnv,WDISPLAY,"\n"); itemName = ""; } gensprintf(buffer,ProfileFunctionData(theEnv)->OutputString, itemName, (long) profileInfo->numberOfEntries,
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -