CMS 3D CMS Logo

Classes | Functions | Variables

cmsPerfClient Namespace Reference

Classes

class  Worker
 Worker This is a subclass of thread that submits commands to the server and stores the result in a thread-safe queue. More...

Functions

def _main
def optionparse
 Option parser returns : Command set to run on each (or all) machines, port to connect to server, List of machines to connect to, File to pickle results to, Dictionary to index which command set to use for which machine.
def presentBenchmarkData
 Format of the returned data from remote host should be of the form (this could be cleaned up a little bit)
def request_benchmark
 Request benchmark Connects to server and returns data returns: profiling data from server.
def runclient

Variables

tuple PROG_NAME = os.path.basename(sys.argv[0])
list validPerfSuitKeys

Function Documentation

def cmsPerfClient::_main ( ) [private]

Definition at line 331 of file cmsPerfClient.py.

00332            :
00333     (cmsperf_cmds, port, hosts, outfile, cmdindex) = optionparse()
00334     runclient(cmsperf_cmds, hosts, port, outfile, cmdindex)

def cmsPerfClient::optionparse ( )

Option parser returns : Command set to run on each (or all) machines, port to connect to server, List of machines to connect to, File to pickle results to, Dictionary to index which command set to use for which machine.

Definition at line 17 of file cmsPerfClient.py.

00018                  :
00019 
00020     #########################
00021     # Config file type validator
00022     # Checks type of configuration options in the config file 
00023     #
00024     def _isValidPerfCmdsDef(alist):
00025         out = True
00026         for item in alist:
00027             isdict = type(item) == type({})
00028             out = out and isdict
00029             if isdict:
00030                 for key in item:
00031                     out = out and key in validPerfSuitKeys
00032                     if   key == "cpus":
00033                         out = out and type(item[key]) == type("") #has to be a string not a list!
00034                     elif key == "cores":
00035                         out = out and type(item[key]) == type("")
00036                     elif key == "castordir":
00037                         out = out and type(item[key]) == type("")
00038                     elif key == "perfsuitedir":
00039                         out = out and type(item[key]) == type("")
00040                     elif key == "TimeSizeEvents":
00041                         out = out and type(item[key]) == type(123)
00042                     elif key == "TimeSizeCandles":
00043                         out = out and type(item[key]) == type("")
00044                     elif key == "CallgrindEvents":
00045                         out = out and type(item[key]) == type(123)
00046                     elif key == "CallgrindCandles":
00047                         out = out and type(item[key]) == type("")
00048                     elif key == "IgProfEvents":
00049                         out = out and type(item[key]) == type(123)
00050                     elif key == "IgProfCandles":
00051                         out = out and type(item[key]) == type("")
00052                     elif key == "MemcheckEvents":
00053                         out = out and type(item[key]) == type(123)
00054                     elif key == "MemcheckCandles":
00055                         out = out and type(item[key]) == type("")
00056                     elif key == "cmsScimark":
00057                         out = out and type(item[key]) == type(123)
00058                     elif key == "cmsScimarkLarge":
00059                         out = out and type(item[key]) == type(123)
00060                     elif key == "cmsdriverOptions":
00061                         out = out and type(item[key]) == type("")
00062                     elif key == "stepOptions":
00063                         out = out and type(item[key]) == type("")
00064                     elif key == "quicktest":
00065                         out = out and type(item[key]) == type(False)
00066                     elif key == "profilers":
00067                         out = out and type(item[key]) == type("")
00068                     elif key == "prevrel":
00069                         out = out and type(item[key]) == type("")
00070                     elif key == "isAllCandles":
00071                         out = out and type(item[key]) == type(False)
00072                     elif key == "candles":
00073                         out = out and type(item[key]) == type("")#has to be a string not a list!
00074                     elif key == "bypasshlt":
00075                         out = out and type(item[key]) == type(False)
00076                     elif key == "runonspare":
00077                         out = out and type(item[key]) == type(False)
00078                     elif key == "logfile":
00079                         out = out and type(item[key]) == type("")
00080         return out
00081 
00082     parser = opt.OptionParser(usage=("""%s [Options]""" % PROG_NAME))
00083 
00084     parser.add_option('-p',
00085                       '--port',
00086                       type="int",
00087                       dest='port',
00088                       default=-1,
00089                       help='Connect to server on a particular port',
00090                       metavar='<PORT>',
00091                       )
00092 
00093     parser.add_option('-o',
00094                       '--output',
00095                       type="string",
00096                       dest='outfile',
00097                       default="",
00098                       help='File to output data to',
00099                       metavar='<FILE>',
00100                       )
00101 
00102     parser.add_option('-m',
00103                       '--machines',
00104                       type="string",
00105                       action="append",
00106                       dest='machines',
00107                       default=[],
00108                       help='Machines to run the benchmarking on, for each machine add another one of these options',
00109                       metavar='<MACHINES>',
00110                       )
00111 
00112     parser.add_option('-f',
00113                       '--cmd-file',
00114                       type="string",
00115                       dest='cmscmdfile',
00116                       action="append",
00117                       default=[],
00118                       help='A files of cmsPerfSuite.py commands to execute on the machines, if more than one of these options is passed and the number of these options is the same as the number of machines, the x-th machine will use the x-th config file.',
00119                       metavar='<PATH>',
00120                       )      
00121 
00122     (options, args) = parser.parse_args()
00123 
00124     ######################
00125     # Check output file location
00126     #
00127     outfile = options.outfile
00128     if not outfile == "": 
00129         outfile = os.path.abspath(options.outfile)
00130         outdir = os.path.dirname(outfile)
00131         if not os.path.isdir(outdir):
00132             parser.error("ERROR: %s is not a valid directory to create %s" % (outdir,os.path.basename(outfile)))
00133             sys.exit()
00134     else:
00135         outfile = os.path.join(os.getcwd(),"cmsmultiperfdata.pypickle")
00136         
00137     if os.path.exists(outfile):
00138         parser.error("ERROR: outfile %s already exists" % outfile)
00139         sys.exit()
00140 
00141 
00142     ###############
00143     # Check configuration files for errors
00144     #
00145     cmsperf_cmds = []
00146     cmscmdfiles = options.cmscmdfile
00147     if len(cmscmdfiles) <= 0:
00148         parser.error("A valid python file defining a list of dictionaries that represents a list of cmsPerfSuite keyword arguments must be passed to this program")
00149         sys.exit()
00150     else:
00151         for cmscmdfile in cmscmdfiles:
00152             cmdfile = os.path.abspath(cmscmdfile)
00153             print cmdfile
00154             if os.path.isfile(cmdfile):
00155                 try:
00156                     execfile(cmdfile)
00157                     cmsperf_cmds.append(listperfsuitekeywords)
00158                 except (SyntaxError), detail:
00159                     parser.error("ERROR: %s must be a valid python file" % cmdfile)
00160                     sys.exit()
00161                 except (NameError), detail:
00162                     parser.error("ERROR: %s must contain a list (variable named listperfsuitekeywords) of dictionaries that represents a list of cmsPerfSuite keyword arguments must be passed to this program: %s" % (cmdfile,str(detail)))
00163                     sys.exit()
00164                 except :
00165                     raise
00166                 if not type(cmsperf_cmds[-1]) == type([]):
00167                     parser.error("ERROR: %s must contain a list (variable named listperfsuitekeywords) of dictionaries that represents a list of cmsPerfSuite keyword arguments must be passed to this program 2" % cmdfile)
00168                     sys.exit()
00169                 if not _isValidPerfCmdsDef(cmsperf_cmds[-1]):
00170                     parser.error("ERROR: %s must contain a list (variable named listperfsuitekeywords) of dictionaries that represents a list of cmsPerfSuite keyword arguments must be passed to this program 3" % cmdfile)
00171                     sys.exit()                
00172 
00173             else:
00174                 parser.error("ERROR: %s is not a file" % cmdfile)
00175                 sys.exit()
00176 
00177     ########
00178     # Setup port number
00179     #
00180     port = 0        
00181     if options.port == -1:
00182         port = 8000
00183     else:
00184         port = options.port
00185 
00186     machines = options.machines
00187 
00188     #################
00189     # Check machine hostnames
00190     #
00191     if len(machines) <= 0:
00192         parser.error("you must specify at least one machine to benchmark")        
00193     else:
00194         machines = map(lambda x: x.strip(),machines)
00195 
00196     for machine in machines:
00197         try:
00198             output = socket.getaddrinfo(machine,port)
00199         except socket.gaierror:
00200             parser.error("ERROR: Can not resolve machine address %s (must be ip{4,6} or hostname)" % machine)
00201             sys.exit()
00202 
00203     ##############
00204     # Define which configuration file to use for which machine
00205     # If only one configuration file is used then it used for all machines
00206     cmdindex = {} # define an index that defines the commands to be run for each machine to be perfsuite'd
00207     if len(cmsperf_cmds) == 1:
00208         for machine in machines:
00209             # each value is the index in cmsperf_cmds that the machine will run
00210             # in this case all machines run the same set of commands
00211             cmdindex[machine] = 0 
00212     else:
00213         if not len(cmsperf_cmds) == len(machines):
00214             parser.error("if more than one configuration file was specified you must specify a configuration file for each machine.")
00215             sys.exit()
00216             
00217         for i in range(len(machines)):
00218             # each value is the index in cmsperf_cmds that the machine will run
00219             # in this case each machine runs the i-th configuration file passed as an option
00220             cmdindex[machine] = i         
00221 
00222     return (cmsperf_cmds, port, machines, outfile, cmdindex)

def cmsPerfClient::presentBenchmarkData (   q,
  outfile 
)

Format of the returned data from remote host should be of the form (this could be cleaned up a little bit)

list of command outputs [ dictionary of cpus { } ]

For example: returned data = [ cmd_output1, cmd_output2 ... ] cmd_output1 = { cpuid1 : cpu_output1, cpuid2 : cpu_output2 ... } # cpuid is "None" if there was only one cpu used cpu_output1 = { candle1 : profset_output1, candle2 : profset_output2 ... } profset_output1 = { profset1 : profile_output1, ... } profile_output1 = { profiletype1: step_output1, ... } step_output1 = { step1: list_of_cpu_times, ... } list_of_cpu_times = [ (evt_num1, secs1), ... ]

We now massage the data

Definition at line 318 of file cmsPerfClient.py.

00319                                    :
00320     print "Pickling data to file %s"%outfile
00321     out = []            # match up the commands with each
00322                         # command that was passed in the config file
00323     while not q.empty():
00324         print "Queue size is still %s"%q.qsize()
00325         (host, data) = q.get()
00326         out.append((host,data))
00327     print "Dumping at screen the output!\n%s"%out
00328     oh = open(outfile,"wb")
00329     pickle.dump(out,oh)
00330     oh.close() 

def cmsPerfClient::request_benchmark (   perfcmds,
  shost,
  sport 
)

Request benchmark Connects to server and returns data returns: profiling data from server.

Definition at line 228 of file cmsPerfClient.py.

00229                                            :
00230     try:
00231         server = xmlrpclib.ServerProxy("http://%s:%s" % (shost,sport))    
00232         return server.request_benchmark(perfcmds)
00233     except socket.error, detail:
00234         print "ERROR: Could not communicate with server %s:%s:" % (shost,sport), detail
00235     except xml.parsers.expat.ExpatError, detail:
00236         print "ERROR: XML-RPC could not be parsed:", detail
00237     except xmlrpclib.ProtocolError, detail:
00238         print "ERROR: XML-RPC protocol error", detail, "try using -L xxx:localhost:xxx if using ssh to forward"
00239     except exceptions, detail:
00240         print "ERROR: There was a runtime error thrown by server %s; detail follows." % shost
00241         print detail

def cmsPerfClient::runclient (   perfcmds,
  hosts,
  port,
  outfile,
  cmdindex 
)

Definition at line 271 of file cmsPerfClient.py.

00272                                                        :
00273     queue = Queue.Queue()
00274     # start all threads
00275     workers = []
00276     for host in hosts:
00277         print "Submitting jobs to %s..." % host
00278         w = Worker(host, port, perfcmds[cmdindex[host]], queue)
00279         w.start()                
00280         workers.append(w)
00281     print "All jobs submitted, waiting for results..."
00282     sys.stdout.flush()
00283     # run until all servers have returned data
00284     while reduce(lambda x,y: x or y, map(lambda x: x.isAlive(),workers)):
00285         try:            
00286             time.sleep(2.0)
00287             sys.stdout.flush()
00288         except (KeyboardInterrupt, SystemExit):
00289             #cleanup
00290             presentBenchmarkData(queue,outfile)            
00291             raise
00292         except:
00293             #cleanup
00294             presentBenchmarkData(queue,outfile)
00295             raise
00296     print "All job results received"
00297     print "The size with the queue containing all data is: %s "%queue.qsize()
00298     presentBenchmarkData(queue,outfile)    


Variable Documentation

tuple cmsPerfClient::PROG_NAME = os.path.basename(sys.argv[0])

Definition at line 6 of file cmsPerfClient.py.

Initial value:
00001 ["castordir", "perfsuitedir" ,"TimeSizeEvents", "TimeSizeCandles","IgProfEvents", "IgProfCandles", "CallgrindEvents", "CallgrindCandles", "MemcheckEvents","MemcheckCandles","cmsScimark", "cmsScimarkLarge",
00002                     "cmsdriverOptions", "stepOptions", "quicktest", "profilers", "cpus", "cores", "prevrel", "isAllCandles", "candles",
00003                     "bypasshlt", "runonspare", "logfile"]

Definition at line 8 of file cmsPerfClient.py.