home *** CD-ROM | disk | FTP | other *** search
- *===============================================================*
- *
- * Profiler.Prg: A General-Purpose Profiler Shell
- *
- * Author: Craig Yellick, Alto Microcomputer, Inc.
- * 7107 Ohms Lane, Minneapolis, Minnesota 55435
- * Voice (612) 835-1080; CIS 76247,541
- *
- * Version: 2.0 * 5-June-90 * DevCon
- *
- * Note: Uses Clipper 5.0-specific syntax, will not
- * operate as-is under Summer '87. However,
- * the code could be modified if needed.
- *
- *---------------------------------------------------------------*
- *
- * No copyrights, no restrictions, no nothin'.
- *
- *---------------------------------------------------------------*
- *
- * What is a profiler? A profiler is a programmer utility that
- * collects information about an application while it is
- * running. This is different from utilities that analyze an
- * application's source code, linker "maps" or other static
- * information. A profiler "watches" your application as it
- * runs, recording information that will be useful to you for
- * debugging or optimizing. Profilers can be programmed to
- * record memory usage, overlay management statistics, timing
- * and speed, disk access or whatever information you need.
- *
- * In this program I present a general purpose profiler shell
- * that you can use as is, or better yet, modify to fit your
- * particular needs. This example profiler makes use of
- * the MEMORY(0) function to give you a very crude estimate
- * of the amount of memory available.
- *
- * I strongly urge you to add support for other kinds of
- * run-time information. For example, I use a memory-usage
- * based profiler to help track down functions that fragment
- * memory or allocate large chunks of memory and don't let go.
- * I use a variation to track execution speed, looking for
- * likely candidates for optimization. Still another variation
- * logs the end-user's progress as they operate the
- * application, giving me insight into how the application is
- * really being used (or abused!) by my customers.
- *
- *---------------------------------------------------------------*
- *
- * Overview: This particular profiler is designed to create
- * and update a text file containing useful information
- * collected while your application is running.
- *
- * It supports two ways to collect information:
- *
- * 1) Via calls to PROFILE() in your source code.
- *
- * 2) Via a hot-key invoked while your application
- * is in a wait-state. Insert the following line
- * early in your application source code:
- *
- * set key <n> to PrfKey // <n> = inkey() value
- *
- *===============================================================*
-
- function PrfKey
- *
- * Target function for calling Profiler via SET KEY TO.
- *
- parameters procName, procLine, readVar
-
- return Profile("*HOTKEY", procName, procLine, readVar)
-
- * end func PrfKey
- *---------------------------------------------------------------*
-
- function Profile
- *
- * The main profiler function.
- *
- * The COMMENT parameter may be specified in a direct call to
- * PROFILE() in source code or from a call via hot-key. Unless
- * the call is via a hot-key, the PROCNAME, PROCLINE and
- * READVAR parameters will not be automatically included.
- * However, if desired, direct calls to PROFILE() may
- * include the PROCNAME(), READVAR() and PROCLINE() functions,
- * or other data of the same type that you find useful.
- *
- * Examples of Direct Calls:
- *
- * Profile("Start of main loop")
- * Profile("Iteration: " +str(i))
- * Profile("Exiting loop", procname(), procline(), readvar())
- * Profile("Exiting loop", VENDOR->Name, VENDOR->(recno()))
- *
- * See PRODEMO.PRG for an example of how to make calling
- * the PROFILE() function easier and cleaner with a
- * preprocessor #DEFINE command.
- *
- * For debugging purposes, PROFILE() returns one of the
- * following exit status codes.
- *
- * 0 No errors
- * 1 Could not open
- * 2 Could not create
- * 3 Could not write
- *
-
- parameter comment, procName, procLine, readVar
-
-
- *** If first call, flag that we've been here
- *
- static prf_init := .t.
- if prf_init
-
- *** Open existing or create new output file.
- *
- * (NOTE: Un-comment the lines if you
- * want the profiler to APPEND to existing
- * files rather than always OVER-WRITING.
- *
- public prf_handle
- * if .not. file("PROFILER.TXT")
- prf_handle= fcreate("PROFILER.TXT", 0)
- if ferror() <> 0
- return 2
- endif
- * else
- * prf_handle= fopen("PROFILER.TXT", 2)
- * if ferror() <> 0
- * return 1
- * endif
- * endif
-
-
- *** One cursory check for an error, we'll
- * assume if one write worked, they all will.
- *
- if .not. PrfOut("", .t.)
- return 3
- endif
-
-
- *** Put a descriptive label in the output file,
- * showing what it is and the date and time started.
- *
- PrfOut("--- SAMPLE PROFILER --- " +dtoc(date()) +" " +time(), .t.)
- PrfOut("", .t.)
-
- *** Output a full set of column headings
- *
- * Insert more column headings, here!
- * \/
- PrfOut("Time Mem-0 Proc-Name Line# Read-Var Comment", .t.)
- PrfOut("-------- ------ ---------- ----- ---------- -------", .t.)
-
- endif // our first time through this function
-
- prf_init= .f.
-
- *** Fix up any missing parameters
- *
- if type("comment") = "U"
- comment= ""
- endif
- if type("procName") = "U"
- procName= ""
- endif
- if type("procLine") = "U"
- procLine= 0
- endif
- if type("readVar") = "U"
- readVar= ""
- endif
-
-
- *** Finally, we're ready to output a line.
- *
- PrfOut(time())
- PrfOut(str(memory(0), 7))
- *
- * Insert more calls to PrfOut() to track
- * things you are interested in.
- *
- PrfOut(" " +left(procName +space(10), 10))
- PrfOut(str(procLine,6))
- PrfOut(" " +left(readVar +space(10), 10))
- PrfOut(" " +comment, .t.)
-
- return 0
-
- * end func Profile
- *---------------------------------------------------------------*
-
- function PrfOut
- *
- * Output a line of text to the profiler file.
- * Optionally appends a CR+LF to end of line.
- * Returns error status.
- *
- * Note: Assumes PRF_HANDLE is public, as defined
- * in PROFILE().
- *
- parameter s, crlf
-
- if pcount() < 2
- crlf= .f.
- endif
-
- fseek(prf_handle, 0, 2) // Move to EOF
-
- fwrite(prf_handle, s +iif(crlf, chr(13) +chr(10), ""))
-
- return (ferror() = 0)
-
- * end func PrfOut
- *===============================================================*
- * eof Profiler.Prg
-