[Dev] event profiling and profile tool

Mike Taylor bear at code-bear.com
Thu Feb 10 16:35:35 PST 2005


That was a similar idea I was working thru to allow for a "Chandler 
Startup" unit test - something that allowed us to test/time the startup 
process.  My thought was also to just script event names and then add a 
basic hook that would inject them into the wx or cpia event queue 
directly.

---
Bear
http://code-bear.com
PGP Fingerprint = 9996 719F 973D B11B E111  D770 9331 E822 40B3 CD29


On Feb 10, 2005, at 7:21 PM, Alec Flett wrote:

> Phillip J. Eby wrote:
>
>> At 10:32 AM 2/10/05 -0800, Ted Leung wrote:
>>
>>> It would also be good to coordinate your CLI with Phillip's code for 
>>> profiling the unit tests...
>>
>>
>> Perhaps my tool should use 'events.prof' instead of 'profile.dat', or 
>> vice versa.  OTOH, if Alec's profile analysis tool accepts the 
>> filename on the command line, then it's of no import.  One could 
>> simply run the unit tests and then run the analysis tool on 
>> profile.dat to analyze the test results.
>>
> Ted and I were talking about this - one thing that would probably be 
> really good to work out is a method of generating events to chandler 
> itself - orthogonal to the unit tests, we probably need a way to 
> simulate at least a few user actions to the full chandler app. Really, 
> this could be as easy as:
> - having a bunch of event names with possible parameters (a few events 
> take parameters) in a text file
> - a command line option for chandler to "execute" this script by just 
> firing off the events listed in the file once the UI has appeared, 
> wait a bit, then quit the app
>
> I think an important thing to know about the event profiling things 
> are that they are based on CPIA events, which are application events - 
> i.e. when someone selects a menu item, and so forth. We can simulate 
> those pretty easily by just dispatching them to the toplevel view.
>
>
>> I'm certainly curious to see the profile navigation.  I seem to 
>> recall that somebody has written a nice GUI for analyzing Python 
>> profiling results but I don't remember where I saw it.  Personally I 
>> haven't had reason to do much with profiler data besides sort the 
>> data a couple different ways and display the top 10 or 20 routines by 
>> time, cumulative time, or number of calls.
>>
> its pretty darn rudamentary (but it does take the filename on the 
> command line) - it runs on the console and its basically stuff like 
> "show callers of <functionName>" or "show stats sorted by <field>" - 
> we probably want a GUI for doing more elaborate analisys, and I would 
> gladly throw it away if you know of a better system out there for 
> analyzing these files.
>
> I've attached the python file here and will try to get it checked in 
> later (so you guys can hack on it :)
> Alec
>
> #!/usr/bin/env python
>
> import getopt, sys, os
> import hotshot, hotshot.stats
> import pstats
> import cStringIO
>
>
> options = { 'filename': None,
>             'order': 'time',
>             'limit': 20,
>             'output': None,
>             'pager': True }
>
> #
> # process_options - processes the options from the command line
> #
> def process_options():
>     optlist, args = getopt.getopt(sys.argv[1:], "p:o:l:c:e:",
>                                   ["profile=",
>                                    "order=",
>                                    "limit=",
>                                    "callers-of=",
>                                    "callees-of="])
>
>
>     for opt, arg in optlist:
>         if (opt == '-p'):
>             options['filename'] = arg
>
>         # need to check valid orders:
>         # calls, cumulative, file, module, pcalls, line, name, nfl, 
> stdname, time
>         if (opt == '-o'):
>             options['order'] = arg
>
>         if (opt == '-l'):
>             options['limit'] = int(arg)
>
>         if (opt == '-c'):
>             options['output'] = 'callers'
>             options['data'] = arg
>
>         if (opt == '-e'):
>             options['output'] = 'callees'
>             options['data'] = arg
>
>     if args and not options['filename']:
>         options['filename'] = args[0]
>
>     if not options['order']:
>         options['order'] = 'time'
>
>     if not options['filename']:
>         print "Filename required..."
>         exit
>
> #
> # prompt_user - prompts the user for an action, and then sets the 
> option
> #               structure to match what they entered
> #
> def prompt_user():
>     while True:
>         try:
>             print "c = callers | e = callees | s = stats | o = order | 
> l = limit";
>
>             line = sys.stdin.readline().strip()
>
>             commandline = line.split(None)
>             command = commandline[0]
>             if len(commandline) > 1:
>                 data = commandline[1]
>             else:
>                 data = None
>
>             if command == 'q':
>                 return False
>
>             if command == 'c':
>                 options['output'] = 'callers'
>                 options['data'] = data
>
>             if command == 'e':
>                 options['output'] = 'callees'
>                 options['data'] = data
>
>             if command == 's':
>                 options['output'] = 'stats'
>                 options['data'] = data
>
>             if command == 'o':
>                 options['order'] = data
>
>             break
>
>         except:
>             print "Unrecognized command"
>
>     return True
>
> #
> # output_with_pager - borrowed from 
> http://www.andreasen.org/misc/util.py
> #
> def output_with_pager(string):
>     print string
>
>     # this seems to be broken right now?
>     less = os.popen('less -', 'w')
>     #try:
>     less.write(string)
>     less.close()
>     #except:
>     pass
>
> #
> # show_profile - displays the profile to the user given the current 
> options
> #
> def show_profile(stats):
>     # stats.strip_dirs()
>     stats.sort_stats(options['order'])
>
>     # now capture the output
>     out = cStringIO.StringIO()
>     old_stdout = sys.stdout
>     sys.stdout = out
>
>     # Figure out the correct part of stats to call
>     try:
>         if options['output'] == 'callers':
>             print "    Callers of '" + options['data'] + "':"
>             stats.print_callers(options['data'], options['limit'])
>         elif options['output'] == 'callees':
>             print "    Functions that '" + options['data'] + "' call:"
>             stats.print_callees(options['data'], options['limit'])
>         else:
>             # show stats
>             print "Statistics: "
>             stats.print_stats(options['limit'])
>
>     except:
>         print "Couldn't generate output. Possibly bad caller/callee 
> pattern"
>
>     # reset to defaults
>     sys.stdout = old_stdout
>     out.seek(0)
>
>     parse_state = None;
>
>     # keep track of where the 2nd column of functions start
>     # we'll find this out from the header
>     col2starts = 0
>
>     result = "";
>     for line in out:
>
>         # funclist1: the first line of the function list
>         if parse_state == 'funclist':
>             function = line[0:col2starts].strip()
>             subfunc = line[col2starts:].strip()
>             if function:
>                 result += "\n" + function + "\n"
>             result += "        " + subfunc + "\n"
>
>         # default parse_state, look for Function header
>         elif line.startswith('Function'):
>             if options['output'] == 'callers':
>                 col2starts = line.find('was called by')
>
>             elif options['output'] == 'callees':
>                 col2starts = line.find('called')
>
>             parse_state = 'funclist'
>         else:
>             result += line + "\n"
>
>     # now spit out to less
>     output_with_pager(result)
>
> #
> # main
> #
> def main():
>
>     process_options()
>
>     stats = hotshot.stats.load(options['filename'])
>     while prompt_user():
>         show_profile(stats)
>
>
> main()
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
>
> Open Source Applications Foundation "Dev" mailing list
> http://lists.osafoundation.org/mailman/listinfo/dev
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PGP.sig
Type: application/pgp-signature
Size: 186 bytes
Desc: This is a digitally signed message part
Url : http://lists.osafoundation.org/pipermail/dev/attachments/20050210/4c5b3e01/PGP.bin


More information about the Dev mailing list