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