Package omero :: Package install :: Module perf_test
[hide private]
[frames] | no frames]

Source Code for Module omero.install.perf_test

  1  #!/usr/bin/env python 
  2   
  3  # 
  4  # Add: screen/plate 
  5  # Add: plotting 
  6  # 
  7   
  8  import re 
  9  import os 
 10  import Ice 
 11  import sys 
 12  import path 
 13  import time 
 14  import uuid 
 15  import omero 
 16  import tables 
 17  import logging 
 18  import optparse 
 19  import fileinput 
 20  import exceptions 
 21   
 22  import omero.cli 
 23  import omero.util 
 24  import omero.util.temp_files 
 25  import omero_Constants_ice 
 26   
 27  command_pattern = "^\s*(\w+)(\((.*)\))?(:(.*))?$" 
 28  command_pattern_compiled = re.compile(command_pattern) 
 29  log = logging.getLogger("omero.perf") 
 30   
 31  FILE_FORMAT = """ 
 32  File format: 
 33      <blank>                                     Ignored 
 34      # comment                                   Ignored 
 35      ServerTime(repeat=100)                      Retrieve the server time 100 times 
 36      Import:<file>                               Import given file 
 37      Import(Screen:<id>):<file>                  Import given file into screen 
 38      Import(Dataset:<id>):<file>                 Import given file into project/dataset 
 39      Import(Project:<id>,Dataset:<id>):<file>    Import given file into project/dataset 
 40      Import(Dataset:some name):<file>            Import given file into a new dataset 
 41      Import(Dataset):<file>                      Import given file into last created dataset (or create a new one) 
 42   
 43      # 
 44      # "Import" is the name of a command available in the current context 
 45      # Use the "--list" command to print them all. All lines must be of the 
 46      # form: %s 
 47   
 48  """ % command_pattern 
 49   
 50  parser = optparse.OptionParser(usage = """usage: %%prog [options] file1 file2 
 51   
 52  Use "-" as a file name to read from stdin. 
 53   
 54  %s""" % FILE_FORMAT) 
 55   
 56  parser.add_option('-l', '--list', action='store_true', help='list available commands') 
 57  parser.add_option('-d', '--debug', action='store_true', help='use DEBUG log level') 
 58  parser.add_option('-H', '--omero.host', action='store', help='host for connection') 
 59  parser.add_option('-P', '--omero.port', action='store', help='port for connection') 
 60  parser.add_option('-W', '--omero.pass', action='store', help='pass for connection') 
 61  parser.add_option('-C', '--Ice.Config', action='store', help='config file for connection') 
 62  #parser.add_option('-c', '--class', action='store', metavar='CLASS', help='special handler CLASS to instantiate') 
 63   
 64   
 65  # 
 66  # Main classes 
 67  # 
 68   
69 -class ItemException(exceptions.Exception): pass
70 -class BadCommand(ItemException): pass
71 -class BadLine(ItemException): pass
72 -class BadPath(ItemException): pass
73 -class BadImport(ItemException): pass
74 75
76 -class Item(object):
77 """ 78 Single line-item in the configuration file 79 """ 80
81 - def __init__(self, line):
82 self.line = line.strip() 83 if not self.comment(): 84 match = command_pattern_compiled.match(self.line) 85 if not match: 86 raise BadLine("Unexpected line: %s" % line) 87 self.command = match.group(1) 88 self.arguments = match.group(3) 89 self.path = match.group(5) 90 self.props = dict() 91 92 if self.arguments: 93 args = self.arguments.split(",") 94 for arg in args: 95 parts = arg.split("=", 1) 96 value = (len(parts) == 2 and parts[1] or "") 97 self.props[parts[0]] = value 98 99 log.debug("Found line: %s, %s, %s, %s", self.command, self.arguments, self.path, self.props)
100
101 - def repeat(self):
102 return int(self.props.get("repeat","1"))
103
104 - def comment(self):
105 if len(self.line) == 0: 106 return True 107 elif self.line.startswith("#"): 108 return True
109
110 - def execute(self, ctx):
111 if self.comment(): 112 return 113 m = getattr(self, "_op_%s" % self.command, None) 114 if m is None: 115 raise BadCommand("Unknown command: %s" % self.command) 116 117 m(ctx)
118
119 - def create_obj(self, ctx, name):
120 id = None 121 id_path = ctx.dir / ("%s.id" % name) 122 prop = self.props.get(name) 123 # Do nothing if not in props 124 if prop is None: 125 return None 126 # If an integer, use that as an id 127 try: 128 id = int(prop) 129 log.debug("Using specified %s:%s" % (name, id)) 130 except: 131 # Otherwise, create/re-use 132 if prop == "": 133 try: 134 id = int(id_path.lines()[0]) 135 except exceptions.Exception, e: 136 log.debug("No %s.id: %s", name, e) 137 prop = str(uuid.uuid4()) 138 # Now, if there's still no id, create one 139 if id is not None: 140 log.debug("Using reload %s:%s" % (name, id)) 141 else: 142 kls = getattr(omero.model, "%sI" % name) 143 obj = kls() 144 obj.name = omero.rtypes.rstring(prop) 145 obj = ctx.update_service().saveAndReturnObject(obj) 146 id = obj.id.val 147 log.debug("Created obj %s:%s" % (name, id)) 148 id_path.write_text(str(id)) 149 return id
150 164
165 - def _op_Import(self, ctx):
166 p = path.path(self.path) 167 if not p.exists(): 168 raise BadPath("File does not exist: %s" % self.path) 169 170 f = str(p.abspath()) 171 out = ctx.dir / ("import_%s.out" % ctx.count) 172 err = ctx.dir / ("import_%s.err" % ctx.count) 173 174 args = ["import", "---file=%s" % str(out), "---errs=%s" % str(err), "-s", ctx.host(), "-k", ctx.key(), f] 175 s_id = self.create_obj(ctx, "Screen") 176 if s_id: 177 args.extend(["-r", str(s_id)]) 178 p_id = self.create_obj(ctx, "Project") 179 d_id = self.create_obj(ctx, "Dataset") 180 if p_id and d_id: 181 self.create_link(ctx, "ProjectDatasetLink", omero.model.ProjectI(p_id, False), omero.model.DatasetI(d_id, False)) 182 if d_id: 183 args.extend(["-d", str(d_id)]) 184 185 ctx.cli.invoke(args) 186 if ctx.cli.rv != 0: 187 raise BadImport("Failed import: rv=%s" % ctx.cli.rv) 188 num_pix = len(out.lines()) 189 log.debug("Import count: %s", num_pix)
190
191 - def _op_ServerTime(self, ctx):
192 ctx.config_service().getServerTime()
193
194 - def _op_LoadFormats(self, ctx):
195 ctx.query_service().findAll("Format", None)
196
197 -class Context(object):
198 """ 199 Login context which can be used by any handler 200 for connecting to a single session. 201 """ 202
203 - def __init__(self, id, reporter = None):
204 205 self.reporters = [] 206 self.count = 0 207 self.id = id 208 self.client = omero.client(id) 209 self.client.setAgent("OMERO.perf_test") 210 self.client.createSession() 211 self.services = {} 212 self.cli = omero.cli.CLI() 213 self.cli.loadplugins() 214 self.setup_dir()
215
216 - def add_reporter(self, reporter):
217 self.reporters.append(reporter)
218
219 - def setup_dir(self):
220 self.dir = path.path(".") / ("perfdir-%s" % os.getpid()) 221 if self.dir.exists(): 222 raise exceptions.Exception("%s exists!" % self.dir) 223 self.dir.makedirs() 224 225 # Adding a file logger 226 handler = logging.handlers.RotatingFileHandler(str(self.dir / "perf.log"), maxBytes = 10000000, backupCount = 5) 227 handler.setLevel(logging.DEBUG) 228 formatter = logging.Formatter(omero.util.LOGFORMAT) 229 handler.setFormatter(formatter) 230 logging.getLogger().addHandler(handler) 231 #log.addHandler(handler) 232 log.debug("Started: %s", time.ctime())
233
234 - def incr(self):
235 self.count += 1
236
237 - def host(self):
238 return self.client.getProperty("omero.host")
239
240 - def key(self):
241 return self.client.sf.ice_getIdentity().name
242
243 - def report(self, command, start, stop, loops, rv):
244 for reporter in self.reporters: 245 reporter.report(command, start, stop, loops, rv)
246
247 - def _stateless(self, name, prx):
248 svc = self.services.get(name) 249 if svc: 250 return svc 251 else: 252 svc = self.client.sf.getByName(name) 253 svc = prx.uncheckedCast(svc) 254 self.services[name] = svc 255 return svc
256
257 - def query_service(self):
258 return self._stateless(omero.constants.QUERYSERVICE, omero.api.IQueryPrx)
259
260 - def config_service(self):
261 return self._stateless(omero.constants.CONFIGSERVICE, omero.api.IConfigPrx)
262
263 - def update_service(self):
264 return self._stateless(omero.constants.UPDATESERVICE, omero.api.IUpdatePrx)
265 266
267 -class PerfHandler(object):
268
269 - def __init__(self, ctx = None):
270 self.ctx = ctx
271
272 - def __call__(self, line):
273 274 (self.ctx.dir/"line.log").write_text(line, append = True) 275 276 item = Item(line) 277 if item.comment(): 278 return 279 280 values = {} 281 total = 0.0 282 self.ctx.incr() 283 start = time.time() 284 loops = item.repeat() 285 for i in range(loops): 286 try: 287 rv = item.execute(self.ctx) 288 except ItemException, ie: 289 log.exception("Error") 290 sys.exit(1) 291 except exceptions.Exception, e: 292 log.debug("Error during execution: %s" % item.line.strip(), exc_info = True) 293 rv = e 294 errs = values.get("errs",0) 295 errs += 1 296 values["errs"] = errs 297 298 if loops > 1: 299 values["avg"] = total / loops 300 301 stop = time.time() 302 total += (stop - start) 303 self.ctx.report(item.command, start, stop, loops, values)
304 305 306 # 307 # Reporter hierarchy 308 # 309 310
311 -class Reporter(object):
312 """ 313 Abstract base class of all reporters 314 """ 315
316 - def report(self, command, start, stop, loops, rv):
317 raise exceptions.Exception("Not implemented")
318 319
320 -class CsvReporter(Reporter):
321
322 - def __init__(self, dir = None):
323 if dir is None: 324 self.stream = sys.stdout 325 else: 326 self.file = str(dir / "report.csv") 327 self.stream = open(self.file, "w") 328 print >>self.stream, "Command,Start,Stop,Elapsed,Average,Values"
329
330 - def report(self, command, start, stop, loops, values):
331 print >>self.stream, "%s,%s,%s,%s,%s,%s" % (command, start, stop, (stop-start), (stop-start)/loops, values) 332 self.stream.flush()
333 334
335 -class HdfReporter(Reporter):
336
337 - def __init__(self, dir):
338 self.file = str(dir / "report.hdf") 339 self.hdf = tables.openFile(self.file, "w") 340 self.tbl = self.hdf.createTable("/", "report", { 341 "Command":tables.StringCol(pos=0, itemsize = 64), 342 "Start":tables.Float64Col(pos=1), 343 "Stop":tables.Float64Col(pos=2), 344 "Elapsed":tables.Float64Col(pos=3), 345 "Average":tables.Float64Col(pos=4), 346 "Values":tables.StringCol(pos=5, itemsize = 1000) 347 }) 348 self.row = self.tbl.row
349
350 - def report(self, command, start, stop, loops, values):
351 self.row["Command"] = command 352 self.row["Start"] = start 353 self.row["Stop"] = stop 354 self.row["Elapsed"] = (stop-start) 355 self.row["Average"] = (stop-start)/loops 356 self.row["Values"] = values 357 self.row.append() 358 self.hdf.flush()
359 360
361 -class PlotReporter(Reporter):
362
363 - def __init__(self):
364 return 365 import matplotlib.pyplot as plt 366 self.fig = plt.figure() 367 self.ax = fig.add_subplot(111)
368
369 - def report(self, command, start, stop, loops, values):
370 return 371 ax.set_ylim(-2,25) 372 ax.set_xlim(0, (last-first)) 373 plt.show()
374 375 ######################################################## 376 377 # 378 # Functions for the execution of this module 379 # 380 381
382 -def usage(prog = sys.argv[0]):
383 return parser.format_help()
384 385
386 -def handle(handler, files):
387 """ 388 Primary method used by the command-line execution of 389 this module. 390 """ 391 392 for line in fileinput.input(files): 393 handler(line) 394 log.debug("Handled %s lines" % handler.ctx.count)
395 396
397 -def main(args, prog = sys.argv[0]):
398 399 parser.prog = prog 400 opts, files = parser.parse_args(args) 401 if opts.list: 402 ops = [ x[4:] for x in dir(Item) if x.startswith("_op_") ] 403 ops.sort() 404 for op in ops: 405 print op 406 sys.exit(0) 407 elif not files: 408 print "No files" 409 print usage() 410 sys.exit(2) 411 412 level = opts.debug and logging.DEBUG or logging.INFO 413 logging.basicConfig(level=level) 414 415 props = [""]+["--%s=%s" % (x, getattr(opts, x, "")) for x in ["omero.host", "omero.port", "omero.pass"]] 416 config = getattr(opts, "Ice.Config", "") 417 if config: 418 props.append("--Ice.Config="+config) 419 id = Ice.InitializationData() 420 id.properties = Ice.createProperties(props) 421 422 ctx = Context(id) 423 print "Running performance tests in %s" % ctx.dir 424 ctx.add_reporter(CsvReporter(ctx.dir)) 425 ctx.add_reporter(HdfReporter(ctx.dir)) 426 ctx.add_reporter(PlotReporter()) 427 handler = PerfHandler(ctx) 428 429 log.debug("Running perf on files: %s", files) 430 handle(handler, files)
431 432 if __name__ == "__main__": 433 args = sys.argv[1:] 434 main(args) 435