def __init__(self, project, options): Analyzer.__init__(self, project) self.commands = {} self.commandHelp = {} self.options = options self.parser = ScriptParser() self.done = False self.colorizer = Console.colorizer self.taskMonitor = Task.RateLimitedTaskMonitor(self) self.profiling = False self.plugins = [] self.traceFiles = {} self.customSyntaxCommands = set() if not self.project.targets: Log.warn("Using empty project file.") if not self.projectHasApiDescription(): Log.warn("Project file does not contain an API description.") # Register internal commands self.registerCommand("quit", self.quit) # Start receiving task notifications Task.setMonitor(self.taskMonitor) # Load all plugins self._loadPlugins()
def main(args): # Parse the command line options options, args = Options.parseCommandLine(args) if options.help_commands: printCommands() return 0 if not args: fail("Command missing. Use one of %s" % ", ".join(getCommands().keys())) command = args[0] commands = getCommands() if options.verbose: Log.quiet = False else: Log.debug = lambda msg: None if options.quiet: Log.quiet = True if not command in commands: fail("Bad command. Use one of %s" % ", ".join(getCommands().keys())) # Install a task monitor taskMon = Task.RateLimitedTaskMonitor(TracyTaskMonitor()) Task.setMonitor(taskMon) # Read the project file project = Project.Project(options=options, fileName=options.project) getCommands()[command][0](project, options, args[1:]) return 0
def main(args): # Parse the command line options options, args = Options.parseCommandLine(args) if options.help_commands: printCommands() return 0 if not args: fail("Command missing. Use one of %s" % ", ".join(getCommands().keys())) command = args[0] commands = getCommands() if options.verbose: Log.quiet = False else: Log.debug = lambda msg: None if options.quiet: Log.quiet = True if not command in commands: fail("Bad command. Use one of %s" % ", ".join(getCommands().keys())) # Install a task monitor taskMon = Task.RateLimitedTaskMonitor(TracyTaskMonitor()) Task.setMonitor(taskMon) # Read the project file project = Project.Project(options = options, fileName = options.project) getCommands()[command][0](project, options, args[1:]) return 0
def notify(self, master_host=None): filter = (lambda task: (not master_host or task['master_host'] == master_host) and task['status'] != Status.RUNNING) for task in self.msg_queue.find(filter): params = Task(task['taskid'], task['sleep_time']).__dict__.copy() params.update({'status': task['status'], 'worker': task['uid']}) status, _ = Conn(task['master_host']).send_recv('/notify', params) if status == 200: # a message is removed only if it is sent successfully # otherwise wait for master to ping and gather this message later self.msg_queue.delete(task['_id'])
def extractWithState(project, trace, firstEvent, lastEvent): """ Extract a portion of a trace much like the slice operations extracts a portion of a list. In addition to the plain extract operation, this operation also extracts events prior to the first event to guarantee that the API state is preserved for the first event. @param project Tracy project. @param trace Source trace @param firstEvent Index of the first event to extract @param lastEvent Index of the last event to extract (non-inclusive) @returns a new trace that contains the extracted events preceeded by collected state setup events. """ newTrace = Trace.Trace() newTrace.sensors = trace.sensors if not trace.events: raise IndexError("Event index out of range") if not "code" in project.targets: raise ValueError("No code information in project file") state = TraceState.TraceState(project) task = Task.startTask("extract-state", "Computing state", len(trace.events[0:firstEvent])) # Extract state setup state.beginCollectingEffectiveEvents() for event in trace.events[0:firstEvent]: state.processEvent(event) task.step() state.endCollectingEffectiveEvents() events = state.getEffectiveEvents() + trace.events[firstEvent:lastEvent] task = Task.startTask("extract-state", "Creating trace", len(events)) baseTime = 0 if events: baseTime = events[0].time # Add the state setup and the extracted events to the new trace for event in events: event = copy.copy(event) event.seq = len(newTrace.events) event.time -= baseTime newTrace.events.append(event) task.step() return newTrace
def load(self): # Determine the trace file size try: self.file.seek(0, 2) fileSize = self.file.tell() self.file.seek(0) except: fileSize = 0 task = Task.startTask("load", "Loading trace", steps = fileSize) # Read and verify version magic version = self.file.read(4) if version != FORMAT_VERSION: raise RuntimeError("Unsupported file format version: %s (%s)" % (version, binascii.hexlify(version))) # First pass: read all the events for i, event in enumerate(self.readEvents()): self.trace.events.append(event) if fileSize: task.updateProgress(self.file.tell()) elif (i & 0xff) == 0: task.step() task.finish() task = Task.startTask("resolve", "Resolving data", len(self.trace.events)) # Second pass: resolve any unknown phrases for event in self.trace.events: if isinstance(event.name, Trace.UnknownPhrase): Log.warn("Event %d name is undefined, trace is probably corrupted." % event.seq) self.trace.events.remove(event) continue for key, value in event.values.items(): if isinstance(key, Trace.UnknownPhrase): Log.warn("Event %d parameter name is undefined, trace is probably corrupted." % event.seq) self.trace.events.remove(event) continue if isinstance(value, Trace.UnknownPhrase): v2 = value value = self.decoder.getPhrase(value.id) if isinstance(value, Trace.UnknownPhrase): #Log.warn("Unable to resolve unknown phrase %s.%s = %s." % (event.name, key, value)) pass else: event.values[key] = value if not value in event.modifiedArrays: event.modifiedArrays.append(value) task.step()
def createAnalyzer(self, args=[]): # Parse the command line options options, args = Options.parseCommandLine(args) # Read the project file project = Project.Project(options=options, fileName=options.project) # Create the interactive analyzer analyzer = Analyzer.InteractiveAnalyzer(project, options) # Divert the output analyzer.reportInfo = self.logInfo Task.setMonitor(None) return analyzer
def createAnalyzer(self, args = []): # Parse the command line options options, args = Options.parseCommandLine(args) # Read the project file project = Project.Project(options = options, fileName = options.project) # Create the interactive analyzer analyzer = Analyzer.InteractiveAnalyzer(project, options) # Divert the output analyzer.reportInfo = self.logInfo Task.setMonitor(None) return analyzer
def saveInstrumentationData(analyzer, trace, instLog): task = Task.startTask("save-instrumentation", "Saving instrumentation data", len(trace.events)) out = open(instLog, "w") # Save the sensor descriptions for name, sensor in trace.sensors.items(): print >>out, "desc", name, sensor.description valueTypeMap = { Trace.IntegerValue: "int", Trace.ShortValue: "int", Trace.ByteValue: "int", Trace.LongValue: "int", Trace.FloatValue: "float", Trace.DoubleValue: "float", int: "int", long: "int", float: "float", str: "str" } # Save the sensor measurements for event in trace.events: task.step() if event.sensorData: print >>out, "event", event.name, event.seq for name, value in event.sensorData.items(): print >>out, "value", valueTypeMap.get(type(value), "str"), name, value # All done out.close()
def compileChecklist(project, trace, items): """ Runs the given trace through a number of checklist items. @param project Tracy project @param trace Trace to examine @param items Checklist item classes @returns a list of processed checklist items (ChecklistItem). """ state = TraceState.TraceState(project) task = Task.startTask("checklist", "Building checklist", len(trace.events)) library = project.targets["code"].library # Initialize the checklist items items = [item(library, trace, state) for item in items] for item in items: item.initialize() for event in trace.events: stateModifiers = state.processEvent(event) for item in items: item.stateModifiers = stateModifiers item.process(event) task.step() for item in items: item.finalize() return items
def saveTrace(self, trace, traceFile): task = Task.startTask("csv-export", "Formatting CSV text", len(trace.events)) fields = ["sequence_number", "time", "name", "duration"] instFields = [] separator = "," # Find out all the needed instrumentation data fields for event in trace.events: for key, value in event.sensorData.items(): if value and not key in instFields: instFields.append(key) instFields = sorted(instFields) # Print out the field header line print >>traceFile, separator.join(fields + instFields) for event in trace.events: f = [str(event.seq), str(event.time), event.name, str(event.duration)] for key in instFields: if key in event.sensorData: f.append(str(event.sensorData[key])) else: f.append("0") print >>traceFile, separator.join(f) task.step()
def saveTrace(self, trace, traceFile): task = Task.startTask("csv-export", "Formatting CSV text", len(trace.events)) fields = ["sequence_number", "time", "name", "duration"] instFields = [] separator = "," # Find out all the needed instrumentation data fields for event in trace.events: for key, value in event.sensorData.items(): if value and not key in instFields: instFields.append(key) instFields = sorted(instFields) # Print out the field header line print >> traceFile, separator.join(fields + instFields) for event in trace.events: f = [ str(event.seq), str(event.time), event.name, str(event.duration) ] for key in instFields: if key in event.sensorData: f.append(str(event.sensorData[key])) else: f.append("0") print >> traceFile, separator.join(f) task.step()
def verify(analyzer, project, trace): # Can't do much without API metadata if not "code" in project.targets: return library = project.targets["code"].library task = Task.startTask("verify", "Verifying trace", len(trace.events)) result = True paramMap = {} for event in trace.events: if not event.name in library.functions: analyzer.reportWarning("Function '%s' not found in library." % event.name) result = False continue func = library.functions[event.name] for name in event.values: if name is None: continue if not name in func.parameters: analyzer.reportWarning("Function '%s' parameter '%s' not found in library." % (event.name, name)) result = False tag = "%s.%s" % (event.name, name) if not tag in paramMap: paramMap[tag] = Console.choose("Please choose the correct parameter", func.parameters.keys()) if paramMap[tag]: newName = paramMap[tag] event.values[newName] = event.values[name] del event.values[name] return result
def extract(trace, firstEvent, lastEvent): """ Extract a portion of a trace much like the slice operations extracts a portion of a list. @param trace Source trace @param firstEvent Index of the first event to extract @param lastEvent Index of the last event to extract (non-inclusive) @returns a new trace that contains just the extracted events. """ newTrace = Trace.Trace() newTrace.sensors = trace.sensors if not trace.events: raise IndexError("Event index out of range") baseTime = trace.events[firstEvent].time task = Task.startTask("extract", "Extracting", len(trace.events[firstEvent:lastEvent])) for event in trace.events[firstEvent:lastEvent]: event = copy.copy(event) event.seq = len(newTrace.events) event.time -= baseTime newTrace.events.append(event) task.step() return newTrace
def computeStateAtEvent(project, trace, eventNumber): """ Compute a trace state at the given event. @param project: Tracy project @param trace: Trace to examine @param eventNumber: Number of event up to which the state is computed. @returns a TraceState instance """ if not trace.events or eventNumber >= len(trace.events): raise IndexError("Event index out of range") if not "code" in project.targets: raise ValueError("No code information in project file") state = TraceState.TraceState(project) task = Task.startTask("compute-state", "Computing state", len(trace.events[:eventNumber])) for event in trace.events[:eventNumber]: state.processEvent(event) task.step() return state
def merge(trace1, trace2, useTimeStamps = False): """ Merge two traces together to produce a single temporally coherent trace. @param trace1 First trace @param trace2 Second trace @returns a new trace that is composed by interleaving the events in trace1 and trace2 sorted by their sequence numbers. """ newTrace = Trace.Trace() newTrace.sensors = trace1.sensors newTrace.sensors.update(trace2.sensors) task = Task.startTask("merge", "Merging traces", len(trace1.events) + len(trace2.events)) # Process trace 1 events for event in trace1.events: event = copy.copy(event) newTrace.events.append(event) task.step() # Process trace 2 events for event in trace2.events: event = copy.copy(event) newTrace.events.append(event) task.step() # Sort the resulting events by their sequence numbers or timestamps if useTimeStamps: newTrace.events.sort(key = lambda event: event.time) else: newTrace.events.sort(key = lambda event: event.seq) return newTrace
def saveInstrumentationData(analyzer, trace, instLog): task = Task.startTask("save-instrumentation", "Saving instrumentation data", len(trace.events)) out = open(instLog, "w") # Save the sensor descriptions for name, sensor in trace.sensors.items(): print >> out, "desc", name, sensor.description valueTypeMap = { Trace.IntegerValue: "int", Trace.ShortValue: "int", Trace.ByteValue: "int", Trace.LongValue: "int", Trace.FloatValue: "float", Trace.DoubleValue: "float", int: "int", long: "int", float: "float", str: "str" } # Save the sensor measurements for event in trace.events: task.step() if event.sensorData: print >> out, "event", event.name, event.seq for name, value in event.sensorData.items(): print >> out, "value", valueTypeMap.get(type(value), "str"), name, value # All done out.close()
def doTask(): master_host = request.args.get('from') taskid = request.args.get('taskid', -1) sleep_time = request.args.get('sleep_time', 0) if master_host: worker.do_task(Task(taskid, sleep_time), master_host) return 'OK' ,200 return 'Rejected, parameters error', 203
def save(self): task = Task.startTask("save", "Saving trace", len(self.trace.events)) # Find out the maximum sizes of all arrays maxSize = {} for event in self.trace.events: for array in event.modifiedArrays: try: elementSize = self.encoder.typeMap[array.__class__][2] except KeyError: print event.name, event.seq, event.values maxSize[array.id] = max(maxSize.get(array.id, 0), elementSize * len(array)) # Write version magic self.file.write(FORMAT_VERSION) for event in self.trace.events: # Update the active API if event.apiId != self.encoder.apiId: self.encoder.apiId = event.apiId token = ApiToken() token.apiId = event.apiId self.file.write(token.save()) # Write a token for the event token = EventToken() token.nameId = self.encoder.defineString(event.name) token.seq = event.seq token.time = event.time self.file.write(token.save()) # Update any modified arrays for array in event.modifiedArrays: # If this is the first definition of this array, extend the array to cover its maximum size. if array.id in maxSize: elementSize = self.encoder.typeMap[array.__class__][2] assert maxSize[array.id] >= elementSize * len(array) array.extend([0] * (maxSize[array.id] / elementSize - len(array))) del maxSize[array.id] self.encoder.encodeValue(array) # Update any modified objects for obj in event.modifiedObjects: self.encoder.encodeValue(obj) # Write a duration token if event.duration: token = DurationToken() token.duration = event.duration self.file.write(token.save()) # Write the parameters for key, value in event.values.items(): token = ValueToken() token.nameId = self.encoder.defineString(key) token.type, token.valueData = self.encoder.encodeValue(value) self.file.write(token.save()) task.step()
def get(self): entry = self.tasks.find_one( {"$or": [{ 'status': Status.CREATED }, { 'status': Status.FAILURE }]}, sort=[('taskid', 1)]) return Task(entry['taskid'], entry['sleep_time']) if entry else None
def save(self): task = Task.startTask("save", "Saving trace", len(self.trace.events)) # Find out the maximum sizes of all arrays maxSize = {} for event in self.trace.events: for array in event.modifiedArrays: try: elementSize = self.encoder.typeMap[array.__class__][2] except KeyError: print event.name, event.seq, event.values maxSize[array.id] = max(maxSize.get(array.id, 0), elementSize * len(array)) for event in self.trace.events: # Update the active API if event.apiId != self.encoder.apiId: self.encoder.apiId = event.apiId token = ApiToken() token.apiId = event.apiId self.file.write(token.save()) # Write a token for the event token = EventToken() token.nameId = self.encoder.defineString(event.name) token.seq = event.seq token.time = event.time self.file.write(token.save()) # Update any modified arrays for array in event.modifiedArrays: # If this is the first definition of this array, extend the array to cover its maximum size. if array.id in maxSize: elementSize = self.encoder.typeMap[array.__class__][2] assert maxSize[array.id] >= elementSize * len(array) array.extend( [0] * (maxSize[array.id] / elementSize - len(array))) del maxSize[array.id] self.encoder.encodeValue(array) # Update any modified objects for obj in event.modifiedObjects: self.encoder.encodeValue(obj) # Write a duration token if event.duration: token = DurationToken() token.duration = event.duration self.file.write(token.save()) # Write the parameters for key, value in event.values.items(): token = ValueToken() token.nameId = self.encoder.defineString(key) token.type, token.valueData = self.encoder.encodeValue(value) self.file.write(token.save()) task.step()
def calculateFrameStatistics(project, trace): """ For each frame marker event, calculate the sum of the instrumentation data for the intermediate events. The instrumentation sensors for each frame marker will contain the aggregate data. @param project: Tracy project @param trace: Trace to examine @returns a list of frame marker events """ if not "code" in project.targets: raise ValueError("No code information in project file") counters = DefaultDict(lambda: 0) avgCounters = DefaultDict(lambda: []) library = project.targets["code"].library task = Task.startTask("calculate-stats", "Computing frame statistics", len(trace.events)) events = [] frameEvents = [] frameStart = 0 trace.sensors["frame_duration"] = Trace.InstrumentationSensor("Frame duration") trace.sensors["event_count"] = Trace.InstrumentationSensor("Event count") for event in trace.events: func = library.functions[event.name] task.step() if func.isFrameMarker: event.sensorData.update(dict([(k, sum(v) / float(len(v))) for k, v in avgCounters.items()])) event.sensorData.update(counters) counters = DefaultDict(lambda: 0) avgCounters = DefaultDict(lambda: []) event.sensorData["frame_duration"] = event.time + event.duration - frameStart event.sensorData["event_count"] = len(frameEvents) frameStart = event.time + event.duration frameEvents = [] events.append(event) else: frameEvents.append(event) for key, value in event.sensorData.items(): if key in trace.sensors and trace.sensors[key].isAverage: try: avgCounters[key].append(float(value)) except ValueError: pass else: try: if isinstance(value, float): counters[key] += value else: counters[key] += int(value) except ValueError: pass return events
def grepTrace(self, traceName, expression, eventRange = None, fullText = True, context = 1, outputTrace = None): """ Search for events matching a regular expression. @param traceName: Trace to examine. @param expression: Regular expression to search for. @param eventRange: Event range to examine. @param fullText: Search full trace text instead of only event names. @param context: Number of events to list around matches. @param outputTrace: Name of trace to save matched events to. """ if not traceName in self.analyzer.traces: self.analyzer.fail("Trace not found: %s" % traceName) trace = self.analyzer.traces[traceName] try: exporter = [e for e in self.analyzer.exportPlugins if e.formatName == "text"][0] except IndexError: self.analyzer.fail("No text format exporter found.") if outputTrace: newTrace = copy.copy(trace) newTrace.events = [] self.analyzer.traces[outputTrace] = newTrace else: newTrace = None tempTrace = copy.copy(trace) def eventToText(event): out = StringIO.StringIO() tempTrace.events = [event] exporter.saveTrace(tempTrace, out, truncateValues = True, includeSensorData = False) return out.getvalue() firstEvent, lastEvent = self.analyzer.parseEventRange(trace, eventRange) fullText = self.analyzer.parseBoolean(fullText) expression = re.compile(expression) task = Task.startTask("grep", "Searching", len(trace.events[firstEvent:lastEvent])) for event in trace.events[firstEvent:lastEvent]: task.step() if fullText: text = eventToText(event) else: text = event.name if expression.search(text): if newTrace: newTrace.events.append(event) else: if not fullText: text = eventToText(event) self.reportInfo(text)
def _msg_handle(ch, method, properties, body): task = Task.from_json(body) if task.param >= 0.9 and datetime.utcnow().microsecond % 2 == 0: logging.warning(f"Failing task: {task.uuid}, re-queueing...") ch.basic_reject(delivery_tag=method.delivery_tag, requeue=True) else: done_task = do(task) logging.info( f"{done_task.worker} done {done_task.uuid} sent by {done_task.sender} in {done_task.took():.3f}s!" ) ch.basic_ack(delivery_tag=method.delivery_tag)
def calculateStatistics(project, trace): """ Calculate derived OpenVG statistics instrumentation sensor data and trace events. """ if not "code" in project.targets: raise ValueError("No code information in project file") task = Task.startTask("vg-stats", "Calculating OpenVG statistics", len(trace.events)) library = project.targets["code"].library constants = Collections.DictProxy(library.constants) # Create the derived sensors trace.sensors["average_path_size"] = Trace.InstrumentationSensor("Average path size", isAverage = True) trace.sensors["image_uploads"] = Trace.InstrumentationSensor("Image uploads") trace.sensors["render_calls"] = Trace.InstrumentationSensor("Rendering calls") trace.sensors["draw_ratio"] = Trace.InstrumentationSensor("Draw ratio") trace.sensors["path_segments"] = Trace.InstrumentationSensor("Path segments") trace.sensors["gradient_stops"] = Trace.InstrumentationSensor("Number of gradient stops defined") prevRenderEvent = None for event in trace.events: task.step() func = library.functions[event.name] if func.isRenderCall: event.sensorData["render_calls"] = 1 if event.name in ["vgSetParameterfv", "vgSetParameteriv"]: if event.values["paramType"] == constants.VG_PAINT_COLOR_RAMP_STOPS: event.sensorData["gradient_stops"] = event.values["count"] / 5 fragments = event.sensorData.get("rasterized_pixels", 0) renderCalls = event.sensorData.get("render_calls", 0) if fragments and renderCalls: event.sensorData["average_path_size"] = fragments / float(renderCalls) if event.name == "vgImageSubData" and "width" in event.values and "height" in event.values: event.sensorData["image_uploads"] = int(event.values["width"] * event.values["height"]) if event.name == "vgAppendPathData": event.sensorData["path_segments"] = int(event.values["numSegments"]) width = event.sensorData.get("render_surface_width", 0) height = event.sensorData.get("render_surface_height", 0) if fragments and width and height: event.sensorData["draw_ratio"] = fragments / float(width * height)
def getImageLoaders(project, trace): """ Return a list of (event, func) pairs, where event is a image upload event and func is a function that returns an Image containing the image data when called. """ library = project.targets["code"].library constants = Collections.DictProxy(library.constants) loaders = [] formats = { constants.VG_sRGBX_8888: ("b", 4, False, False, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000), constants.VG_sRGBA_8888: ("b", 4, False, False, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000), constants.VG_sRGBA_8888_PRE: ("b", 4, False, True, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000), constants.VG_sRGB_565: ("h", 3, False, False, 0x001f, 0x07e0, 0xf800, 0x0), constants.VG_sRGBA_5551: ("h", 4, False, False, 0x001f, 0x03e0, 0x7c00, 0x8000), constants.VG_sRGBA_4444: ("h", 4, False, False, 0x000f, 0x00f0, 0x0f00, 0xf000), constants.VG_sL_8: ("b", 1, False, False, 0xff, 0x0, 0x0, 0x0), constants.VG_lRGBX_8888: ("b", 4, True, False, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000), constants.VG_lRGBA_8888: ("b", 4, True, False, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000), constants.VG_lRGBA_8888_PRE: ("b", 4, True, True, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000), constants.VG_lL_8: ("b", 1, True, False, 0xff, 0x0, 0x0, 0x0), constants.VG_A_8: ("b", 1, True, False, 0xff, 0x0, 0x0, 0x0), constants.VG_BW_1: ("b", 1, True, False, 0x1, 0x0, 0x0, 0x0), } task = Task.startTask("prepare-images", "Looking for images", len(trace.events)) for event in trace.events: task.step() if event.name == "vgImageSubData" and event.values.get("data"): width = event.values["width"] height = event.values["height"] stride = event.values["dataStride"] format = event.values["dataFormat"] if format in formats: unit, components, isLinear, isPremultiplied, redMask, greenMask, blueMask, alphaMask = formats[format] else: continue data = event.values["data"] data = struct.pack("<%d%s" % (len(data), unit), *data) size = (width, height) # Construct copies of the passed variables to make sure the proper data goes into the lambda when called func = lambda d=data, s=size, st=stride, rb=redMask, gb=greenMask, bb=blueMask, ab=alphaMask, il=isLinear, ip=isPremultiplied: \ Graphics.decodeImageData(d, s, st, rb, gb, bb, ab, isLinear = il, isPremultiplied = ip) loaders.append((event, func)) return loaders
def load(self): # Determine the trace file size try: self.file.seek(0, 2) fileSize = self.file.tell() self.file.seek(0) except: fileSize = 0 task = Task.startTask("load", "Loading trace", steps=fileSize) # First pass: read all the events for i, event in enumerate(self.readEvents()): self.trace.events.append(event) if fileSize: task.updateProgress(self.file.tell()) elif (i & 0xff) == 0: task.step() task.finish() task = Task.startTask("resolve", "Resolving data", len(self.trace.events)) # Second pass: resolve any unknown phrases for event in self.trace.events: for key, value in event.values.items(): if isinstance(value, Trace.UnknownPhrase): v2 = value value = self.decoder.getPhrase(value.id) if isinstance(value, Trace.UnknownPhrase): #Log.warn("Unable to resolve unknown phrase %s.%s = %s." % (event.name, key, value)) pass else: event.values[key] = value if not value in event.modifiedArrays: event.modifiedArrays.append(value) task.step()
def load(self): # Determine the trace file size try: self.file.seek(0, 2) fileSize = self.file.tell() self.file.seek(0) except: fileSize = 0 task = Task.startTask("load", "Loading trace", steps = fileSize) # First pass: read all the events for i, event in enumerate(self.readEvents()): self.trace.events.append(event) if fileSize: task.updateProgress(self.file.tell()) elif (i & 0xff) == 0: task.step() task.finish() task = Task.startTask("resolve", "Resolving data", len(self.trace.events)) # Second pass: resolve any unknown phrases for event in self.trace.events: for key, value in event.values.items(): if isinstance(value, Trace.UnknownPhrase): v2 = value value = self.decoder.getPhrase(value.id) if isinstance(value, Trace.UnknownPhrase): #Log.warn("Unable to resolve unknown phrase %s.%s = %s." % (event.name, key, value)) pass else: event.values[key] = value if not value in event.modifiedArrays: event.modifiedArrays.append(value) task.step()
def createEventThumbnails(self, events): # Frame thumbnails task = Task.startTask("create-thumbnails", "Creating thumbnails", len(events)) thumbnails = [] for i, event in enumerate(events): task.step() try: image = player.Instrumentation.loadBuffer(event) if image: image.thumbnail(self.thumbnailSize, resample = True) fn = os.path.join(self.path, "frame_thumbnail%03d.png" % i) image.save(fn) thumbnails.append(Report.Image(fn)) except IOError: continue return thumbnails
def createEventThumbnails(self, events): # Frame thumbnails task = Task.startTask("create-thumbnails", "Creating thumbnails", len(events)) thumbnails = [] for i, event in enumerate(events): task.step() try: image = player.Instrumentation.loadBuffer(event) if image: image.thumbnail(self.thumbnailSize, resample=True) fn = os.path.join(self.path, "frame_thumbnail%03d.png" % i) image.save(fn) thumbnails.append(Report.Image(fn)) except IOError: continue return thumbnails
def read_csv(file_name): with open(file_name) as csv_file: reader = csv.reader(csv_file, delimiter=',') weights = [] sizes = [] costs = [] line_count = 0 for row in reader: if line_count == 0: n_items = int(row[0]) max_weight = int(row[1]) max_size = int(row[2]) logging.info("No of items " + str(n_items) + " max weight: " + str(max_weight) + " max size: " + str(max_size)) line_count += 1 else: weights.append(int(row[0])) sizes.append(int(row[1])) costs.append(int(row[2])) logging.info("Task imported from the csv file") return Task(n_items, max_weight, max_size, weights, sizes, costs)
def join(trace1, trace2): """ Joins two traces together. @param trace1 First trace @param trace2 Second trace @returns a new trace that is composed by joining trace1 and trace2 together in this order. """ newTrace = Trace.Trace() newTrace.sensors = trace1.sensors newTrace.sensors.update(trace2.sensors) baseTime = 0 task = Task.startTask("join", "Joining traces", len(trace1.events) + len(trace2.events)) # Process trace 1 events if trace1.events: baseTime = trace1.events[0].time for event in trace1.events: event = copy.copy(event) event.seq = len(newTrace.events) event.time -= baseTime newTrace.events.append(event) task.step() # Process trace 2 events if trace2.events: baseTime = trace2.events[0].time if newTrace.events: baseTime -= newTrace.events[-1].time + newTrace.events[-1].duration for event in trace2.events: event = copy.deepcopy(event) event.seq = len(newTrace.events) event.time -= baseTime newTrace.events.append(event) task.step() return newTrace
def getImageLoaders(project, trace): """ Return a list of (event, func) pairs, where event is a image upload event and func is a function that returns an Image containing the image data when called. """ library = project.targets["code"].library constants = Collections.DictProxy(library.constants) loaders = [] formats = { constants.VG_sRGBX_8888: ("b", 4, False, False, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000), constants.VG_sRGBA_8888: ("b", 4, False, False, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000), constants.VG_sRGBA_8888_PRE: ("b", 4, False, True, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000), constants.VG_sRGB_565: ("h", 3, False, False, 0x001f, 0x07e0, 0xf800, 0x0), constants.VG_sRGBA_5551: ("h", 4, False, False, 0x001f, 0x03e0, 0x7c00, 0x8000), constants.VG_sRGBA_4444: ("h", 4, False, False, 0x000f, 0x00f0, 0x0f00, 0xf000), constants.VG_sL_8: ("b", 1, False, False, 0xff, 0x0, 0x0, 0x0), constants.VG_lRGBX_8888: ("b", 4, True, False, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000), constants.VG_lRGBA_8888: ("b", 4, True, False, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000), constants.VG_lRGBA_8888_PRE: ("b", 4, True, True, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000), constants.VG_lL_8: ("b", 1, True, False, 0xff, 0x0, 0x0, 0x0), constants.VG_A_8: ("b", 1, True, False, 0xff, 0x0, 0x0, 0x0), constants.VG_BW_1: ("b", 1, True, False, 0x1, 0x0, 0x0, 0x0), } task = Task.startTask("prepare-images", "Looking for images", len(trace.events)) for event in trace.events: task.step() if event.name == "vgImageSubData" and event.values.get("data"): width = event.values["width"] height = event.values["height"] stride = event.values["dataStride"] format = event.values["dataFormat"] if format in formats: unit, components, isLinear, isPremultiplied, redMask, greenMask, blueMask, alphaMask = formats[ format] else: continue data = event.values["data"] data = struct.pack("<%d%s" % (len(data), unit), *data) size = (width, height) # Construct copies of the passed variables to make sure the proper data goes into the lambda when called func = lambda d=data, s=size, st=stride, rb=redMask, gb=greenMask, bb=blueMask, ab=alphaMask, il=isLinear, ip=isPremultiplied: \ Graphics.decodeImageData(d, s, st, rb, gb, bb, ab, isLinear = il, isPremultiplied = ip) loaders.append((event, func)) return loaders
def calculateStatistics(project, trace): """ Calculate derived OpenVG statistics instrumentation sensor data and trace events. """ if not "code" in project.targets: raise ValueError("No code information in project file") task = Task.startTask("vg-stats", "Calculating OpenVG statistics", len(trace.events)) library = project.targets["code"].library constants = Collections.DictProxy(library.constants) # Create the derived sensors trace.sensors["average_path_size"] = Trace.InstrumentationSensor( "Average path size", isAverage=True) trace.sensors["image_uploads"] = Trace.InstrumentationSensor( "Image uploads") trace.sensors["render_calls"] = Trace.InstrumentationSensor( "Rendering calls") trace.sensors["draw_ratio"] = Trace.InstrumentationSensor("Draw ratio") trace.sensors["path_segments"] = Trace.InstrumentationSensor( "Path segments") trace.sensors["gradient_stops"] = Trace.InstrumentationSensor( "Number of gradient stops defined") prevRenderEvent = None for event in trace.events: task.step() func = library.functions[event.name] if func.isRenderCall: event.sensorData["render_calls"] = 1 if event.name in ["vgSetParameterfv", "vgSetParameteriv"]: if event.values[ "paramType"] == constants.VG_PAINT_COLOR_RAMP_STOPS: event.sensorData["gradient_stops"] = event.values["count"] / 5 fragments = event.sensorData.get("rasterized_pixels", 0) renderCalls = event.sensorData.get("render_calls", 0) if fragments and renderCalls: event.sensorData["average_path_size"] = fragments / float( renderCalls) if event.name == "vgImageSubData" and "width" in event.values and "height" in event.values: event.sensorData["image_uploads"] = int(event.values["width"] * event.values["height"]) if event.name == "vgAppendPathData": event.sensorData["path_segments"] = int( event.values["numSegments"]) width = event.sensorData.get("render_surface_width", 0) height = event.sensorData.get("render_surface_height", 0) if fragments and width and height: event.sensorData["draw_ratio"] = fragments / float(width * height)
def calculateStatistics(project, trace): """ Calculate derived OpenGL ES statistics instrumentation sensor data and trace events. """ if not "code" in project.targets: raise ValueError("No code information in project file") task = Task.startTask("gles-stats", "Calculating OpenGL ES statistics", len(trace.events)) library = project.targets["code"].library constants = Collections.DictProxy(library.constants) # Create the derived sensors trace.sensors["average_triangle_size"] = Trace.InstrumentationSensor("Average triangle size", isAverage = True) trace.sensors["texel_fetches_per_pixel"] = Trace.InstrumentationSensor("Texel fetches per pixel", isAverage = True) trace.sensors["texel_uploads"] = Trace.InstrumentationSensor("Texel uploads") trace.sensors["vertices_in"] = Trace.InstrumentationSensor("Vertices in") trace.sensors["triangles_in"] = Trace.InstrumentationSensor("Triangles in") trace.sensors["render_calls"] = Trace.InstrumentationSensor("Rendering calls") trace.sensors["rasterizer_discarded_pixels"] = Trace.InstrumentationSensor("Rasterizer discarded pixels") trace.sensors["draw_ratio"] = Trace.InstrumentationSensor("Draw ratio") prevRenderEvent = None depthMask = 1 for event in trace.events: task.step() func = library.functions[event.name] if func.isRenderCall: event.sensorData["render_calls"] = 1 if func.isRenderCall and "count" in event.values and "mode" in event.values: m = event.values["mode"] if m == constants.GL_TRIANGLES: event.sensorData["triangles_in"] = int(event.values["count"] / 3) elif m == constants.GL_TRIANGLE_STRIP: event.sensorData["triangles_in"] = int(event.values["count"] - 2) elif m == constants.GL_TRIANGLE_FAN: event.sensorData["triangles_in"] = int(event.values["count"] - 2) elif m == constants.GL_POINTS: event.sensorData["triangles_in"] = int(event.values["count"] * 2) elif m == constants.GL_LINES: event.sensorData["triangles_in"] = int(event.values["count"]) elif m == constants.GL_LINE_STRIP: event.sensorData["triangles_in"] = int(event.values["count"] * 2) elif m == constants.GL_LINE_LOOP: event.sensorData["triangles_in"] = int(event.values["count"] * 2 + 2) fragments = event.sensorData.get("rasterizer_pixels", 0) triangles = event.sensorData.get("triangles_in", 0) texFetches = event.sensorData.get("rasterizer_texel_fetches", 0) if triangles and fragments: event.sensorData["average_triangle_size"] = fragments / float(triangles) if fragments and texFetches: event.sensorData["texel_fetches_per_pixel"] = fragments / float(texFetches) if event.name in ["glTexImage2D", "glTexSubImage2D"]: event.sensorData["texel_uploads"] = int(event.values["width"] * event.values["height"]) if func.isRenderCall and "count" in event.values: event.sensorData["vertices_in"] = int(event.values["count"]) if event.name == "glDepthMask": depthMask = event.values["flag"] # If we have the depth buffers for this event and the previous draw event, see how many pixels # actually changed and use that value to estimate overdraw if func.isRenderCall and not "rasterizer_discarded_pixels" in event.sensorData: if depthMask and prevRenderEvent and "depth_stride" in event.sensorData and "depth_mask" in event.sensorData: f1 = player.Instrumentation.getBufferFileName(prevRenderEvent, "depth") f2 = player.Instrumentation.getBufferFileName(event, "depth") if f1 and f2: diff = Graphics.compareDepthBuffers(f1, f2, event.sensorData["depth_stride"], event.sensorData["depth_mask"]) event.sensorData["rasterizer_discarded_pixels"] = fragments - diff prevRenderEvent = event discFragments = event.sensorData.get("rasterizer_discarded_pixels", 0) width = event.sensorData.get("render_surface_width", 0) height = event.sensorData.get("render_surface_height", 0) if fragments and width and height: event.sensorData["draw_ratio"] = (fragments - discFragments) / float(width * height)
def loadInstrumentationData(analyzer, trace, instLog): """ Load precalculated instrumentation data for a trace from an instrumentation log file. @param trace: Trace that should be augmented with the instrumentation data @param instLog: Instrumentation log file name, see instrumentationLogFileName """ logFile = open(instLog) logDir = os.path.dirname(instLog) logFile.seek(0, 2) task = Task.startTask("load-instrumentation", "Loading instrumentation data", logFile.tell()) logFile.seek(0) valueTypeMap = { "int": int, "float": float, "str": str } # Register common sensors trace.sensors["render_surface_width"] = Trace.InstrumentationSensor("Render surface width", isAverage = True) trace.sensors["render_surface_height"] = Trace.InstrumentationSensor("Render surface height", isAverage = True) event = None events = dict([(event.seq, event) for event in trace.events]) for line in logFile.xreadlines(): msg, args = line.rstrip().split(" ", 1) if msg == "event": # Finish off the previous event if event: _postprocessEvent(event, logDir) eventName, seq = args.split(" ", 1) seq = int(seq) # Check that the data refers to a valid event if not seq in events: analyzer.fail("Bad event sequence number: %d" % seq) event = events[seq] if event.name != eventName: analyzer.fail("Event names do not match: %s != %s" % (event.name, eventName)) task.updateProgress(logFile.tell()) elif msg == "value": assert event # Convert and store the value try: valueType, valueName, value = args.split(" ", 2) event.sensorData[valueName] = valueTypeMap[valueType](value) except ValueError: analyzer.reportWarning("Badly formatted sensor value: %s" % line) elif msg == "desc": # Record the sensor description valueName, valueDesc = args.split(" ", 1) if not valueName in trace.sensors: isAverage = valueName in [ "render_surface_width", "render_surface_height", "red_mask", "green_mask", "blue_mask", "alpha_mask", "depth_mask", "stencil_mask", "color_stride", "is_linear", "is_premultiplied", "color_data_type", "depth_data_type", "stencil_data_type" ] trace.sensors[valueName] = Trace.InstrumentationSensor(valueDesc, isAverage = isAverage) else: analyzer.reportWarning("Unknown message received from the player: %s" % line) if event: _postprocessEvent(event, logDir) task.finish() # Call every instrumentation post processor for plugin in analyzer.plugins: try: process = plugin.postProcessInstrumentationData except AttributeError: continue process(trace)
def random_init(self, num=100): # insert tasks with random sleep time for i in range(0, num): self.put(Task(i, randint(1, 5)))
def parseSource(source): """ Parses the given source string and adds all found functions to the library. @param header: Source text @returns: A library containing the parsed functions """ task = Task.startTask("parser", "Parsing type declarations", len(source)) library = Library() # Read the type definitions typedefs = [] for match, pos, l in typedefDecl.scanString(source): task.updateProgress(pos) # Map enumerations to integers if match[0] == "enum": name = match[-1] type = Type("int") for i, e in enumerate(match[1]): enumeration, value = e if value is None: value = i type.addSymbolicConstant(enumeration, value) library.constants[enumeration] = value else: name, type = match[0] library.typeDefs[Type(name)] = type task.finish() # Read preprocessor constants task = Task.startTask("parser", "Parsing preprocessor constants", len(source)) for match, pos, l in preprocessorCommand.scanString(source): task.updateProgress(pos) # Only look for #define if match.command != "define": continue # Only accept integral constants try: value = parseInteger(None, None, [match.value]) except ValueError: continue library.constants[match.name] = value task.finish() def where(pos): return "Line %d, column %s" % (lineno(pos, source), col(pos, source)) task = Task.startTask("parser", "Parsing functions", len(source)) for match, pos, l in function.scanString(source): task.updateProgress(pos) name, type = match.name[0] if not name: continue f = Function(name, type) f.language = "c" for name, type in match.args: if not name or not type: continue f.parameters[name] = Parameter(name, type) # Grab the code if any if match.body: f.body = match.body library.functions[f.name] = f task.finish() return library
def calculateStatistics(self, frameSimilarityFunc=None, timeThreshold=.25, histogramThreshold=.96, frameCountThreshold=20, monochromaticThreshold=.99): # Reset the list of frames self.frames = [] self.interestingFrames = [] # Combine frame level statistics TraceOperations.calculateFrameStatistics(self.project, self.trace) # Calculate some high level statistics events = [] for event in self.trace.events: func = self.library.functions[event.name] events.append(event) if func.isFrameMarker: frame = Frame() frame.startTime = events[0].time / 1e6 frame.endTime = (events[-1].time + events[-1].duration) / 1e6 frame.events = events frame.renderEvents = [ e for e in events if self.library.functions[e.name].isRenderCall ] frame.swapEvent = event frame.number = len(self.frames) # Calculate frame duration frame.duration = frame.endTime - frame.startTime if frame.duration < MIN_FRAME_DURATION: # If the frame has an essentially zero duration, the following event should give a proper time reading try: frame.duration = max( self.trace.events[self.trace.events.index(event) + 1].time / 1e6 - frame.startTime, MIN_FRAME_DURATION) except IndexError: frame.duration = MIN_FRAME_DURATION self.frames.append(frame) events = [] # Now prune the list of frames down to frames of special interest lastFrame = None histograms = {} def getFrameHistogram(frame): if not frame.swapEvent in histograms: try: image = player.Instrumentation.loadBuffer(frame.swapEvent) except: return if image: # Calculate a normalized histogram hist = image.histogram() f = 1.0 / (image.size[0] * image.size[1] * len(image.getbands())) hist = [h * f for h in hist] histograms[frame.swapEvent] = hist return histograms.get(frame.swapEvent) task = Task.startTask("choose-frames", "Choosing interesting frames", len(self.frames)) for frame in self.frames: task.step() if lastFrame and len(self.frames) > frameCountThreshold: # If this frame's duration is pretty much the same as the last one, skip it if abs(frame.duration - lastFrame.duration ) <= timeThreshold * lastFrame.duration: continue # Get color buffer histograms for both images hist1 = getFrameHistogram(frame) hist2 = getFrameHistogram(lastFrame) if hist1 and hist2: # Calculate the Bhattacharyya distance, i.e. the cosine of the angle # between the two histograms dist = sum( [math.sqrt(h2 * h1) for h1, h2 in zip(hist1, hist2)]) # If the distance is close to one, i.e. the frames are nearly identical, # skip this frame. if dist > histogramThreshold: continue # If the frame is mostly just one color, skip it if max(hist1) >= monochromaticThreshold: continue # If we have a similarity function, discard similar frames if frameSimilarityFunc and frameSimilarityFunc( lastFrame, frame): continue # Mark the new frame as interesting self.interestingFrames.append(frame) lastFrame = frame
def simplify(project, trace): """ Simplify a trace by removing redundant GLES commands from it. @param project: Tracy GLES project @param trace: Trace to examine @returns a simplified trace """ if not "code" in project.targets: raise ValueError("No code information in project file") state = TraceState.TraceState(project) newTrace = Trace.Trace() newTrace.sensors = trace.sensors task = Task.startTask("simplify", "Simplifying trace", len(trace.events)) state.beginCollectingEffectiveEvents() for event in trace.events: task.step() """ implicitStateValue = None if event.name == "glPushMatrix": try: depth = state.getValue(["ctx", "matrix_mode", "unit", "stack"]) if depth is None: depth = 0 except KeyError: depth = 0 implicitStateValue = depth + 1 elif event.name == "glPopMatrix": try: depth = state.getValue(["ctx", "matrix_mode", "unit", "stack"]) if depth is None: depth = 0 except KeyError: depth = 0 implicitStateValue = depth - 1 elif event.name == "glActiveTexture": implicitStateValue = event.values["texture"] """ #print ">>>", event.name #print state state.processEvent(event) # If the event doesn't access the state explicitly, it is considered to be a draw call if not state.isStateAccessingEvent(event): state.endCollectingEffectiveEvents() effectiveEvents = state.getEffectiveEvents() i = 0 while i < len(effectiveEvents): # Remove adjacent glPushMatrix()/glPopMatrix() pairs, since they are # an artifact of the state tracker if i < len(effectiveEvents) - 1: if effectiveEvents[i].name == "glPushMatrix" and effectiveEvents[i + 1].name == "glPopMatrix": i += 2 continue newTrace.events.append(effectiveEvents[i]) i += 1 newTrace.events.append(event) state.beginCollectingEffectiveEvents() continue #print state return newTrace
def saveTrace(self, trace, traceFile, dataFileName = None, dataFileFormat = "rvct", frameMarkers = [], initFuncName = "init", uninitFuncName = "uninit", playFuncName = "play", playFrameFuncName = "playFrame", frameFuncName = "frame", arrayPrefix = "array", playerArgument = "context", insertCopyright = True): try: library = self.analyzer.project.targets["code"].library config = self.analyzer.project.config except (AttributeError, KeyError): raise RuntimeError("API configuration not found.") def arrayId(array): assert isinstance(array, Trace.Array) return (array.__class__, array.id) def objectId(obj): assert isinstance(obj, Trace.Object) return "%s_%x_%x" % (obj.cls.name.lower(), obj.ns, obj.id) task = Task.startTask("c-export", "Formatting source", len(trace.events)) indent = " " * 3 # Collect all values for all events task = Task.startTask("c-export", "Collecting data", len(trace.events)) values = [] [values.extend(e.values.values()) for e in trace.events] # Collect arrays arrays = OrderedDict([(arrayId(v), v) for v in reversed(values) if isinstance(v, Trace.Array)]) # Check that the external data format is supported if dataFileName: assert dataFileName.endswith(".s"), "Unsupported external data file type. Use one of: s" assert dataFileFormat in ("gcc", "rvct"), "Unsupported external data format. Use one of: gcc, rvct" dataFile = open(dataFileName, "w") else: dataFile = None # Calculate maximum sizes of arrays arraySizes = dict([(a, 0) for a in arrays.keys()]) for value in values: if isinstance(value, Trace.Array): a = arrayId(value) arraySizes[a] = max(len(value), arraySizes[a]) # Figure out the C types of arrays and objects classes = {} objectTypes = {} arrayTypes = {} outValueObjects = set() # Objects that are acquired through a function arrayVariants = DefaultDict(list) usePersistentArrays = False # Use arrays whose contents must be kept up to date # even after passing them to the API def registerObject(event, name, value): if not value.cls in classes: classes[value.cls] = {} function = self.analyzer.lookupFunction(event) # Object has already been registered if not name or function.parameters[name].isOut: outValueObjects.add(value) if objectId(value) in classes[value.cls]: return classes[value.cls][objectId(value)] = value for cType, nativeTypeName in library.typeMap.items(): if cType.name == value.cls.name: objectTypes[value] = cType break else: self.analyzer.reportWarning("Unknown class: <%s>" % value.cls.name) # Create a fake type name for this class objectTypes[value] = value.cls.name def registerArray(event, name, value): function = self.analyzer.lookupFunction(event) if name: cType = function.parameters[name].type else: cType = function.type # Extract an essential type for the array discarding all qualifiers and modifiers cType = Library.Type(cType.name) # Get the real, non-typedef'd type as well realType = library.resolveType(cType) # If this is a void type, use the original type instead if realType.name == "void": cType = arrayTypeMap[value.__class__] arrayTypes[arrayId(value)] = cType # If this is an object array, register the objects too if isinstance(value, Trace.ObjectArrayValue): for obj in value: registerObject(event, name, obj) for event in trace.events: # OpenGL needs persistent arrays if event.name.startswith("gl"): usePersistentArrays = True for name, value in event.values.items(): if isinstance(value, Trace.Object): registerObject(event, name, value) elif isinstance(value, Trace.Array): registerArray(event, name, value) # Collect the modified arrays for this event for array in event.modifiedArrays: a = arrayId(array) # Only consider the arrays we know about if a in arrayTypes: arrayVariants[a].append(array) task.step() # Count the number of frames if frameMarkers: frameCount = len(frameMarkers) + 3 else: frameCount = len([1 for event in trace.events if self.analyzer.lookupFunction(event).isFrameMarker]) + 3 # Add the header print >>traceFile, "/**" print >>traceFile, " * C source generated from %d events (%d frames). " % (len(trace.events), frameCount) if insertCopyright: print >>traceFile, copyrightText print >>traceFile, " */" print >>traceFile, "" print >>traceFile, "/** A macro for copying data into an array */" print >>traceFile, "#define LOAD_ARRAY(TO, FROM, LENGTH) \\" print >>traceFile, indent, "{ \\" print >>traceFile, indent * 2, "int i; \\" print >>traceFile, indent * 2, "for (i = 0; i < (LENGTH); i++) \\" print >>traceFile, indent * 3, "(TO)[i] = (FROM)[i]; \\" print >>traceFile, indent, "}" print >>traceFile, "" # Insert any additional code specified in the configuration if "c_player_code" in config: for fileName in config["c_player_code"]: f = open(config.getRelativePath(fileName)) print >>traceFile, f.read() f.close() # Add the header to the data file if we have one if dataFile: if dataFileFormat == "gcc": print >>dataFile, "#" print >>dataFile, "# GNU Assembler data file generated from %d events (%d frames). " % (len(trace.events), frameCount) print >>dataFile, "#" print >>dataFile, "" print >>dataFile, ".section .data" else: # rvct print >>dataFile, ";" print >>dataFile, "; RVCT Assembler data file generated from %d events (%d frames). " % (len(trace.events), frameCount) print >>dataFile, ";" print >>dataFile, "" print >>dataFile, " AREA ||.constdata||, DATA, READONLY, ALIGN=2" # Introduce objects print >>traceFile, "/* Objects */ " for objects in classes.values(): for obj in objects.values(): print >>traceFile, "static %s %s = (%s)0x%x;" % (objectTypes[obj], objectId(obj), objectTypes[obj], obj.id) print >>traceFile, "" task.step() # Introduce arrays print >>traceFile, "/* %d arrays */ " % len(arrays) for i, array in enumerate(arrays.values()): a = arrayId(array) if usePersistentArrays: l = arraySizes[a] if not l: self.analyzer.reportWarning("Empty array %s" % str(a)) l = 1 print >>traceFile, "static %s %s_%s%d[%d];" % (arrayTypes[a], str(arrayTypes[a]).lower(), arrayPrefix, i, l) else: print >>traceFile, "static %s* %s_%s%d;" % (arrayTypes[a], str(arrayTypes[a]).lower(), arrayPrefix, i) print >>traceFile, "" # Introduce unique array data print >>traceFile, "/* Array data */ " arrayData = [] arrayMap = {} for variants in arrayVariants.values(): for array in variants: # See if an equivalent array is already created for j, existingArray in enumerate(arrayData): if existingArray == array and \ existingArray.__class__ == array.__class__: arrayMap[id(array)] = j break else: arrayMap[id(array)] = len(arrayData) arrayData.append(array) if not dataFile: # Inline data for i, array in enumerate(arrayData): if not len(array): continue # Object arrays can't be initialized inline if isinstance(array, Trace.ObjectArrayValue): print >>traceFile, "static %s %sData%d[%d];" % (arrayTypes[arrayId(array)], arrayPrefix, i, len(array)) print >>traceFile, "" continue elif usePersistentArrays: print >>traceFile, "static const %s %sData%d[%d] = {" % (arrayTypes[arrayId(array)], arrayPrefix, i, len(array)) else: print >>traceFile, "static %s %sData%d[%d] = {" % (arrayTypes[arrayId(array)], arrayPrefix, i, len(array)) print >>traceFile, indent, # Figure out the proper qualifier for the array elements qualifier = "" format = "s" if len(array): if isinstance(array, Trace.FloatArrayValue): format = qualifier = "f" elif isinstance(array, Trace.DoubleArrayValue): format = qualifier = "d" elif isinstance(array, Trace.LongArrayValue): format = qualifier = "l" for k, value in enumerate(array): value = ("%%%s%s" % (format, qualifier)) % value if k != len(array) - 1: print >>traceFile, "%s," % value, if not (k + 1) % 8: print >>traceFile, "" print >>traceFile, indent, else: print >>traceFile, value print >>traceFile, "};" print >>traceFile, "" else: # External data for i, array in enumerate(arrayData): if not len(array): continue if usePersistentArrays and not isinstance(array, Trace.ObjectArrayValue): print >>traceFile, "extern const %s %sData%d[%d];" % (arrayTypes[arrayId(array)], arrayPrefix, i, len(array)) else: print >>traceFile, "extern %s %sData%d[%d];" % (arrayTypes[arrayId(array)], arrayPrefix, i, len(array)) # Object arrays can't be initialized inline if isinstance(array, Trace.ObjectArrayValue): continue # Figure out the proper type code for the array elements if dataFileFormat == "gcc": print >>dataFile, ".global %sData%d" % (arrayPrefix, i) print >>dataFile, "%sData%d:" % (arrayPrefix, i) if isinstance(array, Trace.FloatArrayValue): typeCode = ".float" elif isinstance(array, Trace.DoubleArrayValue): typeCode = ".double" elif isinstance(array, Trace.LongArrayValue): typeCode = ".quad" elif isinstance(array, Trace.ShortArrayValue): typeCode = ".short" elif isinstance(array, Trace.ByteArrayValue): typeCode = ".byte" elif isinstance(array, Trace.IntegerArrayValue): typeCode = ".int" else: raise RuntimeError("Unknown array type") # Write out the data print >>dataFile, "%s %s" % (typeCode, ", ".join(map(str, array))) else: # rvct print >>dataFile, "GLOBAL %sData%d" % (arrayPrefix, i) print >>dataFile, "%sData%d" % (arrayPrefix, i) if isinstance(array, Trace.FloatArrayValue): typeCode = "DCFS" elif isinstance(array, Trace.DoubleArrayValue): typeCode = "DCFD" elif isinstance(array, Trace.LongArrayValue): typeCode = "DCQ" elif isinstance(array, Trace.ShortArrayValue): typeCode = "DCW" elif isinstance(array, Trace.ByteArrayValue): typeCode = "DCB" elif isinstance(array, Trace.IntegerArrayValue): typeCode = "DCD" else: raise RuntimeError("Unknown array type") # Write out the data prefix = " %s " % typeCode for j in xrange(0, len(array), 8): values = array[j:j + 8] print >>dataFile, prefix, ",".join(map(str, values)) # Initialize the objects print >>traceFile, "static void %s(void* %s)" % (initFuncName, playerArgument) print >>traceFile, "{" def getObjectAttributeValue(attr): if isinstance(attr, Trace.Array): # Only strings are supported so far assert isinstance(attr, Trace.ByteArrayValue) s = "".join((chr(c) for c in attr)) s = s.replace("\r", "\\r") s = s.replace("\t", "\\t") s = s.rstrip("\x00") lines = s.split("\n") return "\n".join(('"%s\\n"' % l for l in lines)) return str(attr) for objects in classes.values(): for obj in objects.values(): # If the object has attributes or it wasn't created from a return value, ask the user to create it cClass = library.classes.get(obj.cls.name) if obj.attrs or (not obj in outValueObjects and cClass and cClass.overridable): print >>traceFile, indent, "/* %s attributes: %s */" % (obj.cls.name, ", ".join(obj.attrs.keys())) if obj.attrs: attrs = ", ".join(map(getObjectAttributeValue, obj.attrs.values())) print >>traceFile, indent, "%s = create%s%d(%s, %s);" % (objectId(obj), obj.cls.name, len(obj.attrs) + 1, playerArgument, attrs) else: print >>traceFile, indent, "%s = create%s1(%s);" % (objectId(obj), obj.cls.name, playerArgument) print >>traceFile, "}" print >>traceFile, "" # Uninitialize the objects print >>traceFile, "static void %s(void* %s)" % (uninitFuncName, playerArgument) print >>traceFile, "{" for objects in classes.values(): for obj in objects.values(): # If the object has attributes or it wasn't created from a return value, ask the user to destroy it cClass = library.classes.get(obj.cls.name) if obj.attrs or (not obj in outValueObjects and cClass and cClass.overridable): print >>traceFile, indent, "destroy%s2(%s, %s);" % (obj.cls.name, playerArgument, objectId(obj)) print >>traceFile, "}" print >>traceFile, "" # Add the events task.finish() task = Task.startTask("c-export", "Generating source", len(trace.events)) frameNumber = 0 frameFunctions = ["%s0" % frameFuncName] activeArrays = dict([(a, None) for a in arrays.keys()]) # Open the frame function print >>traceFile, "static void %s0(void* %s)" % (frameFuncName, playerArgument) print >>traceFile, "{" for event in trace.events: function = self.analyzer.lookupFunction(event) # Modify objects for obj in event.modifiedObjects: # Check the the object was really modified if obj.attrs and obj.attrs != classes[obj.cls][objectId(obj)].attrs: attrs = ", ".join(map(getObjectAttributeValue, obj.attrs.values())) print >>traceFile, indent, "/* %s attributes: %s */" % (obj.cls.name, ", ".join(obj.attrs.keys())) print >>traceFile, indent, "%s = modify%s%d(%s, %s, %s);" % \ (objectId(obj), obj.cls.name, len(obj.attrs) + 2, playerArgument, objectId(obj), attrs) classes[obj.cls][objectId(obj)].attrs = obj.attrs # Modify arrays for array in event.modifiedArrays: # Load the correct data into the array a = arrayId(array) # If this array is not used anywhere, skip it if not id(array) in arrayMap: continue toArray = arrays.index(a) fromArray = arrayMap[id(array)] # Don't reload the same data if activeArrays[a] == fromArray: continue # Ignore empty arrays if not len(array): continue activeArrays[a] = fromArray # Insert new objects directly into the array if isinstance(array, Trace.ObjectArrayValue): for i, obj in enumerate(array): print >>traceFile, indent, "%s_%s%d[%d] = %s;" % \ (str(arrayTypes[a]).lower(), arrayPrefix, toArray, i, objectId(obj)) elif usePersistentArrays: print >>traceFile, indent, "LOAD_ARRAY(%s_%s%d, %sData%d, %d);" % \ (str(arrayTypes[a]).lower(), arrayPrefix, toArray, arrayPrefix, fromArray, len(array)) else: print >>traceFile, indent, "%s_%s%d = %sData%d;" % \ (str(arrayTypes[a]).lower(), arrayPrefix, toArray, arrayPrefix, fromArray) # Collect the arguments args = [] returnValue = None for name, value in event.values.items(): valueType = name and function.parameters[name].type or function.type if value is None: value = "(%s)0" % valueType elif isinstance(value, Trace.Array): # If this array can be modified by the function, mark it as lost if not valueType.isConstant() and value in event.modifiedArrays: a = arrayId(value) activeArrays[a] = None if not value.id: value = "(%s)0" % valueType else: a = arrayId(value) value = "(%s)%s_%s%d" % (valueType, str(arrayTypes[a]).lower(), arrayPrefix, arrays.index(a)) elif isinstance(value, Trace.Object): value = str(objectId(value)) elif isinstance(value, Trace.UnknownPhrase): value = "(%s)NULL" % valueType else: value = StringUtils.decorateValue(library, function, name, value) if isinstance(value, Trace.FloatValue): value = str(value) + "f" elif isinstance(value, Trace.DoubleValue): value = str(value) + "d" elif isinstance(value, Trace.LongValue): value = str(value) + "l" # Do a cast if this is actually a pointer parameter (e.g. 'ptr' in glVertexAttribPointer) if name and library.isPointerType(function.parameters[name].type): value = "(%s)%s" % (valueType, value) # If the real C type is unsigned and we have a negative value, do a cast try: if name and "unsigned" in str(library.resolveType(function.parameters[name].type)) and int(value) < 0: value = "(%s)%s" % (function.parameters[name].type, value) except ValueError: # Not an integer pass # HACK: eglGetDisplay(0) -> eglGetDisplay(EGL_DEFAULT_DISPLAY) if event.name == "eglGetDisplay" and name and str(value) == "0": value = "EGL_DEFAULT_DISPLAY" # Make sure we have a meaningful parameter value assert len(str(value)) if name: args.append(str(value)) else: returnValue = value # Truncated event stream? if not len(args) == len(function.parameters): self.analyzer.reportWarning("Truncated call to %s(%s)" % (event.name, ", ".join(args))) print >>traceFile, indent, "/* truncated call to %s(%s) */" % (event.name, ", ".join(args)) continue # Save the return value if needed returnObject = event.values.get(None, None) if isinstance(returnObject, Trace.Object): print >>traceFile, indent, "%s =" % objectId(returnObject), else: print >>traceFile, indent, args = ", ".join(args) print >>traceFile, "%s(%s);" % (event.name, args) # Apply modifications to object arrays for array in event.modifiedArrays: if isinstance(array, Trace.ObjectArrayValue): for i, obj in enumerate(array): a = arrayId(array) fromArray = arrays.index(a) print >>traceFile, indent, "%s = %s_%s%d[%d];" % \ (objectId(obj), str(arrayTypes[a]).lower(), arrayPrefix, fromArray, i) if (not frameMarkers and function.isFrameMarker) or event in frameMarkers: frameNumber += 1 name = "%s%d" % (frameFuncName, frameNumber) print >>traceFile, "}" print >>traceFile, "" print >>traceFile, "/**" print >>traceFile, " * Frame #%d" % frameNumber print >>traceFile, " */" print >>traceFile, "static void %s(void* %s)" % (name, playerArgument) print >>traceFile, "{" frameFunctions.append(name) task.step() print >>traceFile, "}" print >>traceFile, "" # Create the playback function print >>traceFile, "/**" print >>traceFile, " * Play back all trace frames." print >>traceFile, " * @param %s Optional user data pointer" % (playerArgument) print >>traceFile, " */" print >>traceFile, "static void %s(void* %s)" % (playFuncName, playerArgument) print >>traceFile, "{" print >>traceFile, indent, "%s(%s);" % (initFuncName, playerArgument) for name in frameFunctions: print >>traceFile, indent, "%s(%s);" % (name, playerArgument) print >>traceFile, indent, "%s(%s);" % (uninitFuncName, playerArgument) print >>traceFile, "}" print >>traceFile, "" # Create the playback function for single frame playback print >>traceFile, "/**" print >>traceFile, " * Play back a single frame of the trace." print >>traceFile, " * @param %s Optional user data pointer" % (playerArgument) print >>traceFile, " * @param frame Zero-based number of frame to play" print >>traceFile, " * @returns 1 if the frame number was valid, 0 otherwise" print >>traceFile, " */" print >>traceFile, "static int %s(void* %s, int frame)" % (playFrameFuncName, playerArgument) print >>traceFile, "{" print >>traceFile, indent, "switch (frame)" print >>traceFile, indent, "{" print >>traceFile, indent * 2, "case %6d: %s(%s); break;" % (0, initFuncName, playerArgument) for i, name in enumerate(frameFunctions): print >>traceFile, indent * 2, "case %6d: %s(%s); break;" % (i + 1, name, playerArgument) print >>traceFile, indent * 2, "case %6d: %s(%s); break;" % (len(frameFunctions) + 1, uninitFuncName, playerArgument) print >>traceFile, indent * 2, "default: return 0;" print >>traceFile, indent, "}" print >>traceFile, indent, "return 1;" print >>traceFile, "}" # Close the data file if dataFile: dataFile.close() # All done task.finish()
def loadInstrumentationData(analyzer, trace, instLog): """ Load precalculated instrumentation data for a trace from an instrumentation log file. @param trace: Trace that should be augmented with the instrumentation data @param instLog: Instrumentation log file name, see instrumentationLogFileName """ logFile = open(instLog) logDir = os.path.dirname(instLog) logFile.seek(0, 2) task = Task.startTask("load-instrumentation", "Loading instrumentation data", logFile.tell()) logFile.seek(0) valueTypeMap = {"int": int, "float": float, "str": str} # Register common sensors trace.sensors["render_surface_width"] = Trace.InstrumentationSensor( "Render surface width", isAverage=True) trace.sensors["render_surface_height"] = Trace.InstrumentationSensor( "Render surface height", isAverage=True) event = None events = dict([(event.seq, event) for event in trace.events]) for line in logFile.xreadlines(): msg, args = line.rstrip().split(" ", 1) if msg == "event": # Finish off the previous event if event: _postprocessEvent(event, logDir) eventName, seq = args.split(" ", 1) seq = int(seq) # Check that the data refers to a valid event if not seq in events: analyzer.fail("Bad event sequence number: %d" % seq) event = events[seq] if event.name != eventName: analyzer.fail("Event names do not match: %s != %s" % (event.name, eventName)) task.updateProgress(logFile.tell()) elif msg == "value": assert event # Convert and store the value try: valueType, valueName, value = args.split(" ", 2) event.sensorData[valueName] = valueTypeMap[valueType](value) except ValueError: analyzer.reportWarning("Badly formatted sensor value: %s" % line) elif msg == "desc": # Record the sensor description valueName, valueDesc = args.split(" ", 1) if not valueName in trace.sensors: isAverage = valueName in [ "render_surface_width", "render_surface_height", "red_mask", "green_mask", "blue_mask", "alpha_mask", "depth_mask", "stencil_mask", "color_stride", "is_linear", "is_premultiplied", "color_data_type", "depth_data_type", "stencil_data_type" ] trace.sensors[valueName] = Trace.InstrumentationSensor( valueDesc, isAverage=isAverage) else: analyzer.reportWarning( "Unknown message received from the player: %s" % line) if event: _postprocessEvent(event, logDir) task.finish() # Call every instrumentation post processor for plugin in analyzer.plugins: try: process = plugin.postProcessInstrumentationData except AttributeError: continue process(trace)
for table in tokens.tables: if not table in environment.traces: raise QueryException("Trace does not exist: %s" % table) if tokens.columns == "*": columns = _getAvailableColumns(environment) else: columns = tokens.columns columnNames = [] for column in columns: columnNames.append(".".join(column)) result = Result(columnNames) task = Task.startTask("select", "Selecting events") # Precompile the where-expression if tokens.where[0]: whereExpression = tokens.where[0][1:] whereExpression = _infixToPostfix(whereExpression) else: whereExpression = None # Should we make new traces? for traceName in tokens.intoTables: if traceName in environment.traces: raise QueryException("Can't overwrite existing trace '%s'." % traceName) trace = Trace.Trace() environment.traces[traceName] = trace
pika.ConnectionParameters( host=rmq_host, credentials=pika.credentials.PlainCredentials(username=rmq_user, password=rmq_pass))) rmq_chan = rmq_conn.channel() rmq_chan.basic_qos(prefetch_count=1) rmq_chan.queue_declare(queue=rmq_queue, durable=True) logging.info( f"Sending messages to {rmq_host} to exchange {rmq_exchange} and queue {rmq_queue}..." ) task_cnt = 0 while True: if task_cnt % 10 == 0: logging.info(f"Already sent {task_cnt} messages...") try: task = Task.new(uniform(0., 1.)) rmq_chan.basic_publish(exchange=rmq_exchange, routing_key=rmq_queue, body=task.to_json()) task_cnt += 1 sleep(uniform(0., 0.1)) except KeyboardInterrupt: logging.warning("Keyboard interrupt, exiting!") break except Exception as e: traceback.print_exc() logging.error(e) sleep(1.) if rmq_conn: rmq_conn.close() logging.info(
def generateReport(project, trace, traceFileName, path, format): if traceFileName: title = "OpenGL ES performance report for %s" % os.path.basename(traceFileName) else: title = "OpenGL ES performance report" Log.notice(title) g = ReportGenerator.ReportGenerator(project, trace, title, path, format) # Calculate GLES specific stats GlesTraceOperations.calculateStatistics(project, trace) # Calculate general stats g.calculateStatistics() # Add some general information first section = g.report.create(Report.Section, "General statistics") table = g.createGeneralStatisticsTable() auxiliaryTable = g.createAuxiliaryStatisticsTable() histogramTable = g.createCallHistogramTable() if traceFileName: table.addRow("File name", traceFileName) section.add(table) section.add(auxiliaryTable) section.add(histogramTable) # Add a section about the used render targets addRenderTargetSection(g) # Add an overall timeline of all events g.report.add(g.createEventPlot("Event distribution", trace.events)) # Add a graph about the event type distribution g.report.add(g.createEventFrequencyPlot("Operation distribution", trace.events)) # Add overview section overviewSection = g.report.create(Report.Section, "Overview") # Frame thumbnails thumbnailSection = overviewSection.create(Report.Section, "Selected frames") thumbnails = g.createEventThumbnails([f.swapEvent for f in g.interestingFrames]) for frame, thumbnail in zip(g.interestingFrames, thumbnails): thumbnailSection.create(Report.Link, "#frame%d" % (frame.number + 1), thumbnail) # Textures textureLoaders = GlesTraceOperations.getTextureLoaders(project, trace) if textureLoaders: textureSection = overviewSection.create(Report.Section, "Loaded textures") task = Task.startTask("load-textures", "Loading textures", len(textureLoaders)) for event, func in textureLoaders: task.step() image = func().convert("RGBA") fn = os.path.join(path, "texture%03d.png" % event.seq) image.save(fn) textureSection.create(Report.Image, fn) # FPS data = [1.0 / f.duration for f in g.frames] plot = g.createPlot("Frames per second", range(len(g.frames)), data) overviewSection.add(plot) # Render calls data = [len(f.events) for f in g.frames] plot = g.createPlot("Number of API calls per frame", range(len(g.frames)), data) overviewSection.add(plot) # Overdraw data = [f.swapEvent.sensorData.get("draw_ratio", 0) for f in g.frames] plot = g.createPlot("Draw ratio", range(len(g.frames)), data) overviewSection.add(plot) # Fragment count data = [f.swapEvent.sensorData.get("rasterizer_pixels", 0) for f in g.frames] plot = g.createPlot("Rasterized fragments per frame", range(len(g.frames)), data) overviewSection.add(plot) # Texture reads data = [f.swapEvent.sensorData.get("rasterizer_texel_fetches", 0) for f in g.frames] plot = g.createPlot("Texel fetches per frame", range(len(g.frames)), data) overviewSection.add(plot) # Texture uploads data = [f.swapEvent.sensorData.get("texel_uploads", 0) for f in g.frames] plot = g.createPlot("Texel uploads per frame", range(len(g.frames)), data) overviewSection.add(plot) # Now go over each interesting frame task = Task.startTask("frame-report", "Generating report", len(g.interestingFrames)) frameDetailSection = g.report.create(Report.Section, "Detailed frame statistics") for frame in g.interestingFrames: task.step() frameSection = g.createFrameSection(frame) # Add some custom plots plot = g.createSensorPlot(frame, "rasterizer_pixels") frameSection.add(plot) plot = g.createSensorPlot(frame, "rasterizer_texel_fetches") frameSection.add(plot) plot = g.createSensorPlot(frame, "texel_uploads") frameSection.add(plot) # Now go over the individual render calls + the swap event for event in frame.renderEvents + [frame.swapEvent]: eventSection = g.createEventSection(event) frameSection.add(eventSection) frameDetailSection.add(frameSection) # Add the checklist result g.report.add(g.createChecklistSection("Performance Checklist", GlesChecklist.checklistItems)) # Finalize the report task.finish() g.generate()
def saveTrace(self, trace, traceFile, truncateValues=True, includeSensorData=False): try: library = self.analyzer.project.targets["code"].library except (AttributeError, KeyError): library = None task = Task.startTask("text-export", "Formatting text", len(trace.events)) truncateValues = self.analyzer.parseBoolean(truncateValues) includeSensorData = self.analyzer.parseBoolean(includeSensorData) maxValueLength = 1024 * 1024 # Describe instrumentation sensors if includeSensorData: for name, sensor in sorted(trace.sensors.items()): print >> traceFile, "%010d %010d @inst %s: %s" % ( 0, 0, name, sensor.description) for event in trace.events: try: function = self.analyzer.lookupFunction(event) except: function = None # Print out any associated instrumentation data if includeSensorData: for key, value in sorted(event.sensorData.items()): if value: print >> traceFile, "%010d %010d @inst %s = %s" % ( event.seq, event.time, key, value) # Print out any modified arrays that are not actual parameters for the event. for array in event.modifiedArrays: for value in event.values.values(): if isinstance(value, Trace.Array) and value.id == array.id: break else: if truncateValues: text = StringUtils.ellipsis(array, maxLength=maxValueLength) else: text = array print >> traceFile, "%010d %010d @array 0x%x = %s" % ( event.seq, event.time, array.id, text) args = [] # Print out the parameters for name, value in event.values.items(): if not name: continue if function and library: value = StringUtils.decorateValue(library, function, name, value) if truncateValues: value = StringUtils.ellipsis(value, maxLength=maxValueLength) args += ["%s=%s" % (name, value)] print >> traceFile, "%010d %010d %s (%s)" % ( event.seq, event.time, event.name, ", ".join(args)), if None in event.values: print >> traceFile, "-> %s" % event.values[ None], "+%d" % event.duration else: print >> traceFile, "+%d" % event.duration task.step()
def get_task_(self): status, data = Conn(self.taskpool_host).send_recv('/get') if status != 200 or not data: return None qs = parse_qs(data) return Task(qs['taskid'][0], qs['sleep_time'][0])
def generateReport(project, trace, traceFileName, path, format): if traceFileName: title = "OpenVG performance report for %s" % os.path.basename( traceFileName) else: title = "OpenVG performance report" g = ReportGenerator.ReportGenerator(project, trace, title, path, format) # Calculate VG specific stats #VgTraceOperations.calculateStatistics(project, trace) # Calculate general stats g.calculateStatistics() # Add some general information first section = g.report.create(Report.Section, "General statistics") table = g.createGeneralStatisticsTable() if traceFileName: table.addRow("File name", traceFileName) section.add(table) # Add an overall timeline of all events g.report.add(g.createEventPlot("Event distribution", trace.events)) # Add a graph about the event type distribution g.report.add( g.createEventFrequencyPlot("Operation distribution", trace.events)) # Add overview section overviewSection = g.report.create(Report.Section, "Overview") # Frame thumbnails thumbnailSection = overviewSection.create(Report.Section, "Selected frames") thumbnails = g.createEventThumbnails( [f.swapEvent for f in g.interestingFrames]) for frame, thumbnail in zip(g.interestingFrames, thumbnails): thumbnailSection.create(Report.Link, "#frame%d" % (frame.number + 1), thumbnail) # Images imageLoaders = VgTraceOperations.getImageLoaders(project, trace) if imageLoaders: imageSection = overviewSection.create(Report.Section, "Loaded images") task = Task.startTask("load-images", "Loading images", len(imageLoaders)) for event, func in imageLoaders: task.step() image = func().convert("RGBA") fn = os.path.join(path, "image%03d.png" % event.seq) image.save(fn) imageSection.create(Report.Image, fn) # FPS data = [1.0 / f.duration for f in g.frames] plot = g.createPlot("Frames per second", range(len(g.frames)), data) overviewSection.add(plot) # Render calls data = [len(f.events) for f in g.frames] plot = g.createPlot("Number of API calls per frame", range(len(g.frames)), data) overviewSection.add(plot) # Fragment count data = [ f.swapEvent.sensorData.get("rasterized_pixels", 0) for f in g.frames ] plot = g.createPlot("Rasterized fragments per frame", range(len(g.frames)), data) overviewSection.add(plot) # Now go over each interesting frame task = Task.startTask("frame-report", "Generating report", len(g.interestingFrames)) frameDetailSection = g.report.create(Report.Section, "Detailed frame statistics") for frame in g.interestingFrames: task.step() frameSection = g.createFrameSection(frame) # Add some custom plots plot = g.createSensorPlot(frame, "rasterized_pixels") frameSection.add(plot) # Now go over the individual render calls + the swap event for event in frame.renderEvents + [frame.swapEvent]: eventSection = g.createEventSection(event) frameSection.add(eventSection) frameDetailSection.add(frameSection) # Add the checklist result #g.report.add(g.createChecklistSection("Performance Checklist", VgChecklist.checklistItems)) # Finalize the report task.finish() g.generate()
def assign_task(self, task): '''增加作业''' self.tasks.put(Task.from_dict(task))
def getTextureLoaders(project, trace): """ Return a list of (event, func) pairs, where event is a texture upload event and func is a function that returns an Image containing the texture data when called. """ library = project.targets["code"].library constants = Collections.DictProxy(library.constants) loaders = [] componentCount = { constants.GL_ALPHA: 1, constants.GL_RGB: 3, constants.GL_RGBA: 4, constants.GL_LUMINANCE: 1, constants.GL_LUMINANCE_ALPHA: 2, } task = Task.startTask("prepare-textures", "Looking for textures", len(trace.events)) for event in trace.events: task.step() # We don't handle compressed texture formats if event.name in ["glTexImage2D", "glTexSubImage2D"] and event.values.get("pixels"): width = event.values["width"] height = event.values["height"] format = event.values["format"] type = event.values["type"] if format in componentCount: components = componentCount[format] else: continue if type == constants.GL_UNSIGNED_BYTE: bytesPerPixel = components format = "b" redMask = 0x00ff0000 greenMask = 0x0000ff00 blueMask = 0x000000ff alphaMask = 0xff000000 elif type == constants.GL_UNSIGNED_SHORT_5_6_5: bytesPerPixel = 2 format = "h" redMask = 0x001f greenMask = 0x07e0 blueMask = 0xf800 alphaMask = 0x0000 elif type == constants.GL_UNSIGNED_SHORT_5_5_5_1: bytesPerPixel = 2 format = "h" redMask = 0x001f greenMask = 0x03e0 blueMask = 0x7c00 alphaMask = 0x8000 elif type == constants.GL_UNSIGNED_SHORT_4_4_4_4: bytesPerPixel = 2 format = "h" redMask = 0x000f greenMask = 0x00f0 blueMask = 0x0f00 alphaMask = 0xf000 else: continue pixels = event.values["pixels"] data = struct.pack("<%d%s" % (len(pixels), format), *pixels) if components < 4: alphaMask = 0 if components < 3: blueMask = 0 if components < 2: greenMask = 0 size = (width, height) stride = width * bytesPerPixel # Construct copies of the passed variables to make sure the proper data goes into the lambda when called func = lambda d=data, s=size, st=stride, rb=redMask, gb=greenMask, bb=blueMask, ab=alphaMask: \ Graphics.decodeImageData(d, s, st, rb, gb, bb, ab) loaders.append((event, func)) return loaders
def grepTrace(self, traceName, expression, eventRange=None, fullText=True, context=1, outputTrace=None): """ Search for events matching a regular expression. @param traceName: Trace to examine. @param expression: Regular expression to search for. @param eventRange: Event range to examine. @param fullText: Search full trace text instead of only event names. @param context: Number of events to list around matches. @param outputTrace: Name of trace to save matched events to. """ if not traceName in self.analyzer.traces: self.analyzer.fail("Trace not found: %s" % traceName) trace = self.analyzer.traces[traceName] try: exporter = [ e for e in self.analyzer.exportPlugins if e.formatName == "text" ][0] except IndexError: self.analyzer.fail("No text format exporter found.") if outputTrace: newTrace = copy.copy(trace) newTrace.events = [] self.analyzer.traces[outputTrace] = newTrace else: newTrace = None tempTrace = copy.copy(trace) def eventToText(event): out = StringIO.StringIO() tempTrace.events = [event] exporter.saveTrace(tempTrace, out, truncateValues=True, includeSensorData=False) return out.getvalue() firstEvent, lastEvent = self.analyzer.parseEventRange( trace, eventRange) fullText = self.analyzer.parseBoolean(fullText) expression = re.compile(expression) task = Task.startTask("grep", "Searching", len(trace.events[firstEvent:lastEvent])) for event in trace.events[firstEvent:lastEvent]: task.step() if fullText: text = eventToText(event) else: text = event.name if expression.search(text): if newTrace: newTrace.events.append(event) else: if not fullText: text = eventToText(event) self.reportInfo(text)
def calculateStatistics(self, frameSimilarityFunc = None, timeThreshold = .25, histogramThreshold = .96, frameCountThreshold = 20, monochromaticThreshold = .99): # Reset the list of frames self.frames = [] self.interestingFrames = [] # Combine frame level statistics TraceOperations.calculateFrameStatistics(self.project, self.trace) # Calculate some high level statistics events = [] for event in self.trace.events: func = self.library.functions[event.name] events.append(event) if func.isFrameMarker: frame = Frame() frame.startTime = events[0].time / 1e6 frame.endTime = (events[-1].time + events[-1].duration) / 1e6 frame.events = events frame.renderEvents = [e for e in events if self.library.functions[e.name].isRenderCall] frame.swapEvent = event frame.number = len(self.frames) # Calculate frame duration frame.duration = frame.endTime - frame.startTime if frame.duration < MIN_FRAME_DURATION: # If the frame has an essentially zero duration, the following event should give a proper time reading try: frame.duration = max(self.trace.events[self.trace.events.index(event) + 1].time / 1e6 - frame.startTime, MIN_FRAME_DURATION) except IndexError: frame.duration = MIN_FRAME_DURATION self.frames.append(frame) events = [] # Now prune the list of frames down to frames of special interest lastFrame = None histograms = {} def getFrameHistogram(frame): if not frame.swapEvent in histograms: try: image = player.Instrumentation.loadBuffer(frame.swapEvent) except: return if image: # Calculate a normalized histogram hist = image.histogram() f = 1.0 / (image.size[0] * image.size[1] * len(image.getbands())) hist = [h * f for h in hist] histograms[frame.swapEvent] = hist return histograms.get(frame.swapEvent) task = Task.startTask("choose-frames", "Choosing interesting frames", len(self.frames)) for frame in self.frames: task.step() if lastFrame and len(self.frames) > frameCountThreshold: # If this frame's duration is pretty much the same as the last one, skip it if abs(frame.duration - lastFrame.duration) <= timeThreshold * lastFrame.duration: continue # Get color buffer histograms for both images hist1 = getFrameHistogram(frame) hist2 = getFrameHistogram(lastFrame) if hist1 and hist2: # Calculate the Bhattacharyya distance, i.e. the cosine of the angle # between the two histograms dist = sum([math.sqrt(h2 * h1) for h1, h2 in zip(hist1, hist2)]) # If the distance is close to one, i.e. the frames are nearly identical, # skip this frame. if dist > histogramThreshold: continue # If the frame is mostly just one color, skip it if max(hist1) >= monochromaticThreshold: continue # If we have a similarity function, discard similar frames if frameSimilarityFunc and frameSimilarityFunc(lastFrame, frame): continue # Mark the new frame as interesting self.interestingFrames.append(frame) lastFrame = frame
def saveTrace(self, trace, traceFile, dataFileName=None, dataFileFormat="rvct", frameMarkers=[], initFuncName="init", uninitFuncName="uninit", playFuncName="play", playFrameFuncName="playFrame", frameFuncName="frame", arrayPrefix="array", playerArgument="context", insertCopyright=True): try: library = self.analyzer.project.targets["code"].library config = self.analyzer.project.config except (AttributeError, KeyError): raise RuntimeError("API configuration not found.") def arrayId(array): assert isinstance(array, Trace.Array) return (array.__class__, array.id) def objectId(obj): assert isinstance(obj, Trace.Object) return "%s_%x_%x" % (obj.cls.name.lower(), obj.ns, obj.id) task = Task.startTask("c-export", "Formatting source", len(trace.events)) indent = " " * 3 # Collect all values for all events task = Task.startTask("c-export", "Collecting data", len(trace.events)) values = [] [values.extend(e.values.values()) for e in trace.events] # Collect arrays arrays = OrderedDict([(arrayId(v), v) for v in reversed(values) if isinstance(v, Trace.Array)]) # Check that the external data format is supported if dataFileName: assert dataFileName.endswith( ".s"), "Unsupported external data file type. Use one of: s" assert dataFileFormat in ( "gcc", "rvct" ), "Unsupported external data format. Use one of: gcc, rvct" dataFile = open(dataFileName, "w") else: dataFile = None # Calculate maximum sizes of arrays arraySizes = dict([(a, 0) for a in arrays.keys()]) for value in values: if isinstance(value, Trace.Array): a = arrayId(value) arraySizes[a] = max(len(value), arraySizes[a]) # Figure out the C types of arrays and objects classes = {} objectTypes = {} arrayTypes = {} outValueObjects = set() # Objects that are acquired through a function arrayVariants = DefaultDict(list) usePersistentArrays = False # Use arrays whose contents must be kept up to date # even after passing them to the API def registerObject(event, name, value): if not value.cls in classes: classes[value.cls] = {} function = self.analyzer.lookupFunction(event) # Object has already been registered if not name or function.parameters[name].isOut: outValueObjects.add(value) if objectId(value) in classes[value.cls]: return classes[value.cls][objectId(value)] = value for cType, nativeTypeName in library.typeMap.items(): if cType.name == value.cls.name: objectTypes[value] = cType break else: self.analyzer.reportWarning("Unknown class: <%s>" % value.cls.name) # Create a fake type name for this class objectTypes[value] = value.cls.name def registerArray(event, name, value): function = self.analyzer.lookupFunction(event) if name: cType = function.parameters[name].type else: cType = function.type # Extract an essential type for the array discarding all qualifiers and modifiers cType = Library.Type(cType.name) # Get the real, non-typedef'd type as well realType = library.resolveType(cType) # If this is a void type, use the original type instead if realType.name == "void": cType = arrayTypeMap[value.__class__] arrayTypes[arrayId(value)] = cType # If this is an object array, register the objects too if isinstance(value, Trace.ObjectArrayValue): for obj in value: registerObject(event, name, obj) for event in trace.events: # OpenGL needs persistent arrays if event.name.startswith("gl"): usePersistentArrays = True for name, value in event.values.items(): if isinstance(value, Trace.Object): registerObject(event, name, value) elif isinstance(value, Trace.Array): registerArray(event, name, value) # Collect the modified arrays for this event for array in event.modifiedArrays: a = arrayId(array) # Only consider the arrays we know about if a in arrayTypes: arrayVariants[a].append(array) task.step() # Count the number of frames if frameMarkers: frameCount = len(frameMarkers) + 3 else: frameCount = len([ 1 for event in trace.events if self.analyzer.lookupFunction(event).isFrameMarker ]) + 3 # Add the header print >> traceFile, "/**" print >> traceFile, " * C source generated from %d events (%d frames). " % ( len(trace.events), frameCount) if insertCopyright: print >> traceFile, copyrightText print >> traceFile, " */" print >> traceFile, "" print >> traceFile, "/** A macro for copying data into an array */" print >> traceFile, "#define LOAD_ARRAY(TO, FROM, LENGTH) \\" print >> traceFile, indent, "{ \\" print >> traceFile, indent * 2, "int i; \\" print >> traceFile, indent * 2, "for (i = 0; i < (LENGTH); i++) \\" print >> traceFile, indent * 3, "(TO)[i] = (FROM)[i]; \\" print >> traceFile, indent, "}" print >> traceFile, "" # Insert any additional code specified in the configuration if "c_player_code" in config: for fileName in config["c_player_code"]: f = open(config.getRelativePath(fileName)) print >> traceFile, f.read() f.close() # Add the header to the data file if we have one if dataFile: if dataFileFormat == "gcc": print >> dataFile, "#" print >> dataFile, "# GNU Assembler data file generated from %d events (%d frames). " % ( len(trace.events), frameCount) print >> dataFile, "#" print >> dataFile, "" print >> dataFile, ".section .data" else: # rvct print >> dataFile, ";" print >> dataFile, "; RVCT Assembler data file generated from %d events (%d frames). " % ( len(trace.events), frameCount) print >> dataFile, ";" print >> dataFile, "" print >> dataFile, " AREA ||.constdata||, DATA, READONLY, ALIGN=2" # Introduce objects print >> traceFile, "/* Objects */ " for objects in classes.values(): for obj in objects.values(): print >> traceFile, "static %s %s = (%s)0x%x;" % ( objectTypes[obj], objectId(obj), objectTypes[obj], obj.id) print >> traceFile, "" task.step() # Introduce arrays print >> traceFile, "/* %d arrays */ " % len(arrays) for i, array in enumerate(arrays.values()): a = arrayId(array) if usePersistentArrays: l = arraySizes[a] if not l: self.analyzer.reportWarning("Empty array %s" % str(a)) l = 1 print >> traceFile, "static %s %s_%s%d[%d];" % ( arrayTypes[a], str( arrayTypes[a]).lower(), arrayPrefix, i, l) else: print >> traceFile, "static %s* %s_%s%d;" % ( arrayTypes[a], str(arrayTypes[a]).lower(), arrayPrefix, i) print >> traceFile, "" # Introduce unique array data print >> traceFile, "/* Array data */ " arrayData = [] arrayMap = {} for variants in arrayVariants.values(): for array in variants: # See if an equivalent array is already created for j, existingArray in enumerate(arrayData): if existingArray == array and \ existingArray.__class__ == array.__class__: arrayMap[id(array)] = j break else: arrayMap[id(array)] = len(arrayData) arrayData.append(array) if not dataFile: # Inline data for i, array in enumerate(arrayData): if not len(array): continue # Object arrays can't be initialized inline if isinstance(array, Trace.ObjectArrayValue): print >> traceFile, "static %s %sData%d[%d];" % ( arrayTypes[arrayId(array)], arrayPrefix, i, len(array)) print >> traceFile, "" continue elif usePersistentArrays: print >> traceFile, "static const %s %sData%d[%d] = {" % ( arrayTypes[arrayId(array)], arrayPrefix, i, len(array)) else: print >> traceFile, "static %s %sData%d[%d] = {" % ( arrayTypes[arrayId(array)], arrayPrefix, i, len(array)) print >> traceFile, indent, # Figure out the proper qualifier for the array elements qualifier = "" format = "s" if len(array): if isinstance(array, Trace.FloatArrayValue): format = qualifier = "f" elif isinstance(array, Trace.DoubleArrayValue): format = qualifier = "d" elif isinstance(array, Trace.LongArrayValue): format = qualifier = "l" for k, value in enumerate(array): value = ("%%%s%s" % (format, qualifier)) % value if k != len(array) - 1: print >> traceFile, "%s," % value, if not (k + 1) % 8: print >> traceFile, "" print >> traceFile, indent, else: print >> traceFile, value print >> traceFile, "};" print >> traceFile, "" else: # External data for i, array in enumerate(arrayData): if not len(array): continue if usePersistentArrays and not isinstance( array, Trace.ObjectArrayValue): print >> traceFile, "extern const %s %sData%d[%d];" % ( arrayTypes[arrayId(array)], arrayPrefix, i, len(array)) else: print >> traceFile, "extern %s %sData%d[%d];" % ( arrayTypes[arrayId(array)], arrayPrefix, i, len(array)) # Object arrays can't be initialized inline if isinstance(array, Trace.ObjectArrayValue): continue # Figure out the proper type code for the array elements if dataFileFormat == "gcc": print >> dataFile, ".global %sData%d" % (arrayPrefix, i) print >> dataFile, "%sData%d:" % (arrayPrefix, i) if isinstance(array, Trace.FloatArrayValue): typeCode = ".float" elif isinstance(array, Trace.DoubleArrayValue): typeCode = ".double" elif isinstance(array, Trace.LongArrayValue): typeCode = ".quad" elif isinstance(array, Trace.ShortArrayValue): typeCode = ".short" elif isinstance(array, Trace.ByteArrayValue): typeCode = ".byte" elif isinstance(array, Trace.IntegerArrayValue): typeCode = ".int" else: raise RuntimeError("Unknown array type") # Write out the data print >> dataFile, "%s %s" % (typeCode, ", ".join( map(str, array))) else: # rvct print >> dataFile, "GLOBAL %sData%d" % (arrayPrefix, i) print >> dataFile, "%sData%d" % (arrayPrefix, i) if isinstance(array, Trace.FloatArrayValue): typeCode = "DCFS" elif isinstance(array, Trace.DoubleArrayValue): typeCode = "DCFD" elif isinstance(array, Trace.LongArrayValue): typeCode = "DCQ" elif isinstance(array, Trace.ShortArrayValue): typeCode = "DCW" elif isinstance(array, Trace.ByteArrayValue): typeCode = "DCB" elif isinstance(array, Trace.IntegerArrayValue): typeCode = "DCD" else: raise RuntimeError("Unknown array type") # Write out the data prefix = " %s " % typeCode for j in xrange(0, len(array), 8): values = array[j:j + 8] print >> dataFile, prefix, ",".join(map(str, values)) # Initialize the objects print >> traceFile, "static void %s(void* %s)" % (initFuncName, playerArgument) print >> traceFile, "{" def getObjectAttributeValue(attr): if isinstance(attr, Trace.Array): # Only strings are supported so far assert isinstance(attr, Trace.ByteArrayValue) s = "".join((chr(c) for c in attr)) s = s.replace("\r", "\\r") s = s.replace("\t", "\\t") s = s.rstrip("\x00") lines = s.split("\n") return "\n".join(('"%s\\n"' % l for l in lines)) return str(attr) for objects in classes.values(): for obj in objects.values(): # If the object has attributes or it wasn't created from a return value, ask the user to create it cClass = library.classes.get(obj.cls.name) if obj.attrs or (not obj in outValueObjects and cClass and cClass.overridable): print >> traceFile, indent, "/* %s attributes: %s */" % ( obj.cls.name, ", ".join(obj.attrs.keys())) if obj.attrs: attrs = ", ".join( map(getObjectAttributeValue, obj.attrs.values())) print >> traceFile, indent, "%s = create%s%d(%s, %s);" % ( objectId(obj), obj.cls.name, len(obj.attrs) + 1, playerArgument, attrs) else: print >> traceFile, indent, "%s = create%s1(%s);" % ( objectId(obj), obj.cls.name, playerArgument) print >> traceFile, "}" print >> traceFile, "" # Uninitialize the objects print >> traceFile, "static void %s(void* %s)" % (uninitFuncName, playerArgument) print >> traceFile, "{" for objects in classes.values(): for obj in objects.values(): # If the object has attributes or it wasn't created from a return value, ask the user to destroy it cClass = library.classes.get(obj.cls.name) if obj.attrs or (not obj in outValueObjects and cClass and cClass.overridable): print >> traceFile, indent, "destroy%s2(%s, %s);" % ( obj.cls.name, playerArgument, objectId(obj)) print >> traceFile, "}" print >> traceFile, "" # Add the events task.finish() task = Task.startTask("c-export", "Generating source", len(trace.events)) frameNumber = 0 frameFunctions = ["%s0" % frameFuncName] activeArrays = dict([(a, None) for a in arrays.keys()]) # Open the frame function print >> traceFile, "static void %s0(void* %s)" % (frameFuncName, playerArgument) print >> traceFile, "{" for event in trace.events: function = self.analyzer.lookupFunction(event) # Modify objects for obj in event.modifiedObjects: # Check the the object was really modified if obj.attrs and obj.attrs != classes[obj.cls][objectId( obj)].attrs: attrs = ", ".join( map(getObjectAttributeValue, obj.attrs.values())) print >> traceFile, indent, "/* %s attributes: %s */" % ( obj.cls.name, ", ".join(obj.attrs.keys())) print >>traceFile, indent, "%s = modify%s%d(%s, %s, %s);" % \ (objectId(obj), obj.cls.name, len(obj.attrs) + 2, playerArgument, objectId(obj), attrs) classes[obj.cls][objectId(obj)].attrs = obj.attrs # Modify arrays for array in event.modifiedArrays: # Load the correct data into the array a = arrayId(array) # If this array is not used anywhere, skip it if not id(array) in arrayMap: continue toArray = arrays.index(a) fromArray = arrayMap[id(array)] # Don't reload the same data if activeArrays[a] == fromArray: continue # Ignore empty arrays if not len(array): continue activeArrays[a] = fromArray # Insert new objects directly into the array if isinstance(array, Trace.ObjectArrayValue): for i, obj in enumerate(array): print >>traceFile, indent, "%s_%s%d[%d] = %s;" % \ (str(arrayTypes[a]).lower(), arrayPrefix, toArray, i, objectId(obj)) elif usePersistentArrays: print >>traceFile, indent, "LOAD_ARRAY(%s_%s%d, %sData%d, %d);" % \ (str(arrayTypes[a]).lower(), arrayPrefix, toArray, arrayPrefix, fromArray, len(array)) else: print >>traceFile, indent, "%s_%s%d = %sData%d;" % \ (str(arrayTypes[a]).lower(), arrayPrefix, toArray, arrayPrefix, fromArray) # Collect the arguments args = [] returnValue = None for name, value in event.values.items(): valueType = name and function.parameters[ name].type or function.type if value is None: value = "(%s)0" % valueType elif isinstance(value, Trace.Array): # If this array can be modified by the function, mark it as lost if not valueType.isConstant( ) and value in event.modifiedArrays: a = arrayId(value) activeArrays[a] = None if not value.id: value = "(%s)0" % valueType else: a = arrayId(value) value = "(%s)%s_%s%d" % (valueType, str( arrayTypes[a]).lower(), arrayPrefix, arrays.index(a)) elif isinstance(value, Trace.Object): value = str(objectId(value)) elif isinstance(value, Trace.UnknownPhrase): value = "(%s)NULL" % valueType else: value = StringUtils.decorateValue(library, function, name, value) if isinstance(value, Trace.FloatValue): value = str(value) + "f" elif isinstance(value, Trace.DoubleValue): value = str(value) + "d" elif isinstance(value, Trace.LongValue): value = str(value) + "l" # Do a cast if this is actually a pointer parameter (e.g. 'ptr' in glVertexAttribPointer) if name and library.isPointerType( function.parameters[name].type): value = "(%s)%s" % (valueType, value) # If the real C type is unsigned and we have a negative value, do a cast try: if name and "unsigned" in str( library.resolveType(function.parameters[name]. type)) and int(value) < 0: value = "(%s)%s" % (function.parameters[name].type, value) except ValueError: # Not an integer pass # HACK: eglGetDisplay(0) -> eglGetDisplay(EGL_DEFAULT_DISPLAY) if event.name == "eglGetDisplay" and name and str( value) == "0": value = "EGL_DEFAULT_DISPLAY" # Make sure we have a meaningful parameter value assert len(str(value)) if name: args.append(str(value)) else: returnValue = value # Truncated event stream? if not len(args) == len(function.parameters): self.analyzer.reportWarning("Truncated call to %s(%s)" % (event.name, ", ".join(args))) print >> traceFile, indent, "/* truncated call to %s(%s) */" % ( event.name, ", ".join(args)) continue # Save the return value if needed returnObject = event.values.get(None, None) if isinstance(returnObject, Trace.Object): print >> traceFile, indent, "%s =" % objectId(returnObject), else: print >> traceFile, indent, args = ", ".join(args) print >> traceFile, "%s(%s);" % (event.name, args) # Apply modifications to object arrays for array in event.modifiedArrays: if isinstance(array, Trace.ObjectArrayValue): for i, obj in enumerate(array): a = arrayId(array) fromArray = arrays.index(a) print >>traceFile, indent, "%s = %s_%s%d[%d];" % \ (objectId(obj), str(arrayTypes[a]).lower(), arrayPrefix, fromArray, i) if (not frameMarkers and function.isFrameMarker) or event in frameMarkers: frameNumber += 1 name = "%s%d" % (frameFuncName, frameNumber) print >> traceFile, "}" print >> traceFile, "" print >> traceFile, "/**" print >> traceFile, " * Frame #%d" % frameNumber print >> traceFile, " */" print >> traceFile, "static void %s(void* %s)" % ( name, playerArgument) print >> traceFile, "{" frameFunctions.append(name) task.step() print >> traceFile, "}" print >> traceFile, "" # Create the playback function print >> traceFile, "/**" print >> traceFile, " * Play back all trace frames." print >> traceFile, " * @param %s Optional user data pointer" % ( playerArgument) print >> traceFile, " */" print >> traceFile, "static void %s(void* %s)" % (playFuncName, playerArgument) print >> traceFile, "{" print >> traceFile, indent, "%s(%s);" % (initFuncName, playerArgument) for name in frameFunctions: print >> traceFile, indent, "%s(%s);" % (name, playerArgument) print >> traceFile, indent, "%s(%s);" % (uninitFuncName, playerArgument) print >> traceFile, "}" print >> traceFile, "" # Create the playback function for single frame playback print >> traceFile, "/**" print >> traceFile, " * Play back a single frame of the trace." print >> traceFile, " * @param %s Optional user data pointer" % ( playerArgument) print >> traceFile, " * @param frame Zero-based number of frame to play" print >> traceFile, " * @returns 1 if the frame number was valid, 0 otherwise" print >> traceFile, " */" print >> traceFile, "static int %s(void* %s, int frame)" % ( playFrameFuncName, playerArgument) print >> traceFile, "{" print >> traceFile, indent, "switch (frame)" print >> traceFile, indent, "{" print >> traceFile, indent * 2, "case %6d: %s(%s); break;" % ( 0, initFuncName, playerArgument) for i, name in enumerate(frameFunctions): print >> traceFile, indent * 2, "case %6d: %s(%s); break;" % ( i + 1, name, playerArgument) print >> traceFile, indent * 2, "case %6d: %s(%s); break;" % ( len(frameFunctions) + 1, uninitFuncName, playerArgument) print >> traceFile, indent * 2, "default: return 0;" print >> traceFile, indent, "}" print >> traceFile, indent, "return 1;" print >> traceFile, "}" # Close the data file if dataFile: dataFile.close() # All done task.finish()
def saveTrace(self, trace, traceFile, truncateValues = True, includeSensorData = False): try: library = self.analyzer.project.targets["code"].library except (AttributeError, KeyError): library = None task = Task.startTask("text-export", "Formatting text", len(trace.events)) truncateValues = self.analyzer.parseBoolean(truncateValues) includeSensorData = self.analyzer.parseBoolean(includeSensorData) maxValueLength = 1024 * 1024 # Describe instrumentation sensors if includeSensorData: for name, sensor in sorted(trace.sensors.items()): print >>traceFile, "%010d %010d @inst %s: %s" % (0, 0, name, sensor.description) for event in trace.events: try: function = self.analyzer.lookupFunction(event) except: function = None # Print out any associated instrumentation data if includeSensorData: for key, value in sorted(event.sensorData.items()): if value: print >>traceFile, "%010d %010d @inst %s = %s" % (event.seq, event.time, key, value) # Print out any modified arrays that are not actual parameters for the event. for array in event.modifiedArrays: for value in event.values.values(): if isinstance(value, Trace.Array) and value.id == array.id: break else: if truncateValues: text = StringUtils.ellipsis(array, maxLength = maxValueLength) else: text = array print >>traceFile, "%010d %010d @array 0x%x = %s" % (event.seq, event.time, array.id, text) args = [] # Print out the parameters for name, value in event.values.items(): if not name: continue if function and library: value = StringUtils.decorateValue(library, function, name, value) if truncateValues: value = StringUtils.ellipsis(value, maxLength = maxValueLength) args += ["%s=%s" % (name, value)] print >>traceFile, "%010d %010d %s (%s)" % (event.seq, event.time, event.name, ", ".join(args)), if None in event.values: print >>traceFile, "-> %s" % event.values[None], "+%d" % event.duration else: print >>traceFile, "+%d" % event.duration task.step()
def reload(self): task = Task.startTask("reload", "Reloading plugins", len(sys.modules)) for plugin in self.plugins: reload(sys.modules[plugin.__module__])