Piyasa profiler (c)2002 Edivision, LLC
except piCAutoFunct.c GNU/FSF, GPL.PIYASA RELEASE VERION 0.9Contents:


Special Thanks to John Harris for donating his time and knowledge to create the piyasa.inc VP include.

LICENSE
You are permitted to use all software in this package except piCAutoFunct.c under the following conditions. See GPL.txt for restrictions on use of piCAutoFunct. The following refers to parts of the package other than piCAutoFunct. All rights remain the property of Edivision, LLC. Permission is granted for both commercial and non-commercial usage. If you modify any part of this program you may not redistribute the modified version, but please consider sending the modifications to Edivision for inclusion in the official archive. If you use and include this product as part of any other product it must 1) not make up more than 40% of the new product, and 2) show in a conspicuous location the following text: "Piyasa (c)2002 Edivision LLC by Patrick Roberts". If you use this product in the creation of , but don't include it or any part within any product you are not required to show any information concerning Piyasa. No warranty is expressed or implied. No guarante expressed or implied except that this version of this software provided as open-source under this licenses cannot in the future be switched to any other license. Future revisions and version may be released under a different license. This product may not be redistributed except in its full, unmodified form and the distributor may not charge more the actual cost of providing the archive. The author reserves the right to waive any restrictions. Contributed works incorporated into the Piyasa distribution automatically fall under this same license where no previous license existed before.

Known Issues:


Using Piyasa

To profile an application, or part of an application with Piyasa there are 3 sequential steps. First, the source code must have the appropriate calls added to it before compiling. Second, the application compiled with 'PROFILE' defined must be ran and Piyasa data gathered. Third, the Piyasa output data can be parsed and rewritten into a more human-readable format. When compiled with defines disabling profiling, no piyasa code is included in the final output executable/library. Step 1: Marking up the source code

In order for Piyasa to write out data detailing execution time, function marcos need to be added to the code. You can do this manually or automatically as explained below. Some defines however must be made manually and are covered in Step 2: Compiling and Running Marked-up code.

Manual Marking.

There are 4 functions you can use to have Piyasa gather information about your code. They are piFunctIn(), piFunctOut(), piUserStart(), and piUserEnd(). These are all defined in <edivision/piyasa.h>, which must be included in your sourcecode.

piFunctIn() and piFunctOut() are used at the start and end of a function. They take a single argument, which is a function identification number. You may use any number you like, but it is required that each function inside the same source file have a unique nummber. Programs which mark up the source manually will normally start at 1000, so if you wish to use both you are safe using numbers under 1000. You can, but it is not necessary, give a unique number to each function in every source file. Here is an example of how this is used:

int main(int argc, char **argv) {piFunctIn(1002);{

return piFunctOut(1002), 0;

} piFunctOut(1002);}

You can see here how piFunctIn() and piFunctOut() are used with a function definition, return statement, and end of function marker.

piUserStart() and piUserEnd() can be added anywhere in your code you like. Piyasa will begin profiling at piUserStart() and end at piUserEnd(). These can be used to wrap and monitor things like inner loops. Each of these take a single argument, which is a unique text lable. The text lable must be unique for all source files compiled together.

piUserStart("bar_loop");

i=rand()&0xFFFFFF;

for(f=0;f<i;f++);

piUserEnd("bar_loop");

Here, we want to check the performance of some useless loop, which is called 'bar_loop'. The formatted output will refer to this by the label.

Automatic Marking

Automatic marking programs take a source file on stdin and output a marked-up version on stdout. Only function blocks are marked for profiling. Currently, the only supplied auto-marker is piyCAuto, which is for C files. (In the future hopefully someone will extend Piyasa and create a VP auto-marker.) It will add the necessary #includes and piFunctIn()s and piFunctOut()s. You may still need to add defines depending on how complex your compile is. See the included test directory for examples of how to use piyCauto.

Step 2: Compiling and Running Marked-Up Code

There are several compiler defines that control Piyasa. At a minimum you must define PROFILE or PIYASA, otherwise Piyasa will default to inactive and no profiling code will be included in the compiled software.

PIYASA_OUT

This controls where the Piysasa data will be written. The default is to stderr for redirection to a file during execution. You can redefine this to stdout, or a global file pointer for an initialized file or stream. This variable is passed as the output stream to fprintf().

PIYASA_FSNUM

This is defined as an integer and is added to your piFunctIn()/Out() unique ID numbers. This define allows multiple files compiled together which have conflicting unique ID function numbers to be resolved manually. In the example above where main() is tagged as 1002, if PIYASA_FSNUM were defined before it as 200, it would actually have the value 1202. Using the automarker can generate conflicting numbers so it is a good idea to ifdef->undef->def a unique PIYASA_FSNUM for each source file you which to profile in. Make sure you number is large enough to not cause additional conflicts.

When the code is ready to compile, create an executable and run it. Be sure if your PIYASA_OUT is set to stdout or stderr that you redirect your output to a file. Output text which makes it into the file should not cause a problem. Your program will run quite a bit slower due to the file i/o, however it does not effect the relative performance of profiled blocks of code, especially when then are executed multiple times.

Step 3: Processing the Piyasa Output

After running you should have a Piyasa raw output file (.piy). It will look something like this:

Sf|160806023262000|00001002|main
Sf|160806023285000|00001000|foo
Ef|160806023363000|00001000|foo
Sf|160806023373000|00001001|bar
Su|160806023387000|bar_loop|bar
Eu|160806067145000|bar_loop|bar
Ef|160806067169000|00001001|bar
Sf|160806067178000|00001000|foo
Ef|160806067217000|00001000|foo
Sf|160806067227000|00001001|bar
Su|160806067240000|bar_loop|bar
Eu|160806091166000|bar_loop|bar
It may also be quite large (several hundred megs). There are filters that will convert this file into something more useful. Don't worry if your .piy file has text that is part of your program's normal output. The filters will simply issue a warning on stderr saying they can't understand the line. Filters take the input file on stdin and output the formatted report on stdout. Currently Piyasa has 2 filtering programs: piy2text and piy2csv.

Piy2text will process the file and give you a simple text summary. Here is an example of the output:

4 items
f: main calls:1 avg:328904000ns min:328904000ns max:328904000ns
f: foo calls:11 avg:22090ns min:13000ns max:78000ns
f: bar calls:10 avg:32845100ns min:14395000ns max:47567000ns
u: bar_loop (bar) calls:10 avg:32822200ns min:14373000ns max:47547000ns
Here you can see each function call and user block. The first character of each line is an 'f' for a function block, or a 'u' for a user block. After that.is the name of the function for a function block, or the name of the user block with the function it occurs inside of. Next is the number of times the function was encountered or called. Then the average, min, and maximum time it took to execute the code. (NOTE: An extremely large 'max' may be the result of file I/O issues.) The total time spent in the code can be calulated by multiplying calls by avg.

Piy2cvs exports a comma-separated value file suitable for importing into a spreadsheep application. Here is an example of one imported into Kspread:

At the left you can see the names f the functions, followed by various data. Total Time Value is a result of multiplying times called by average time. A function name with a * as the last character is a function that had an odd number of blocks (more In()s than Out()s). This can occur from a user break or from the program calling exit(). Piyasa attempts not to factor in odd blocks, and if one occurs becuase of a break or exit() it shouldn't impact the stats. If one occurs for another reason the marked-up code needs to be checked.

Writing output filters
Creating output filters is fairly easy. They should follow the same format as the the existing filters- start with piy2, take input on stdin, output to stdout, and ignore lines it doesn't understand. There is even a supplied C file which has a routine to parse the output and return a filled structure array. See the src directory for exmaple c code.

It is strongly recommended that the supplied parser be used, but if you wish to create your own documentation on the output follows.

Piyasa output format:

Sf|160806023262000|00001002|main
Sf|160806023285000|00001000|foo
Ef|160806023363000|00001000|foo
Sf|160806023373000|00001001|bar
Su|160806023387000|bar_loop|bar
Eu|160806067145000|bar_loop|bar
Ef|160806067169000|00001001|bar
Sf|160806067178000|00001000|foo
Ef|160806067217000|00001000|foo
Sf|160806067227000|00001001|bar
Su|160806067240000|bar_loop|bar
Eu|160806091166000|bar_loop|bar
In the above example output you can see each line has 4 fields separated by a vertical bar.

The first is a 2 character code that identifies the type of entry. The first character is 'S' for start or 'E' for end and 'f' is for function and 'u' for user block.

The second field is a long (64-bit) number which is a timestamp.

The third field is either a unique ID number for a function entry (f), or the unique label for a user entry (u).

The Last field is the name of the function in which the entry was generated.


Using Piyasa with VP

  Using Piyasa with VP is very similar to its use in C.  There are only a couple of differenced.  First, you need to include 'edivision/piyasa.inc'.  The user blocks function exactly the same as with C, however, the function blocks need to be passed the function name rather than the ID number.  (This is because currently there is no VP equal for the c preprocessor's __FUNCTION__ define.).