1
2
3
4
5
6
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
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
51
52
58
59
61 """
62 Single line-item in the configuration file
63 """
64
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
86 return int(self.props.get("repeat","1"))
87
93
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
104 id = None
105 id_path = ctx.dir / ("%s.id" % name)
106 prop = self.props.get(name)
107
108 if prop is None:
109 return None
110
111 try:
112 id = int(prop)
113 log.debug("Using specified %s:%s" % (name, id))
114 except:
115
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
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
136 link = ctx.query_service().findByQuery(\
137 "select link from %s link where link.parent.id = %s and link.child.id = %s"\
138 % (kls_name, parent.id.val, child.id.val), None)
139 if link:
140 log.debug("Found link %s:%s" % (kls_name, link.id.val))
141 else:
142 kls = getattr(omero.model, "%sI" % kls_name)
143 obj = kls()
144 obj.parent = parent
145 obj.child = child
146 obj = ctx.update_service().saveAndReturnObject(obj)
147 log.debug("Created link %s:%s" % (kls_name, obj.id.val))
148
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
177
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
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
219 log.debug("Started: %s", time.ctime())
220
223
225 return self.client.getProperty("omero.host")
226
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
255
258
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
295
296
297
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
308
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
323
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):
347
348
350
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
367
368
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