예제 #1
0
파일: Analyzer.py 프로젝트: se210/tracy
  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()
예제 #2
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
예제 #3
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
예제 #4
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'])
예제 #5
0
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
예제 #6
0
파일: BinaryCodec.py 프로젝트: se210/tracy
  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()
예제 #7
0
    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
예제 #8
0
파일: AnalyzerTest.py 프로젝트: se210/tracy
  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
예제 #9
0
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()
예제 #10
0
파일: Checklist.py 프로젝트: se210/tracy
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
예제 #11
0
파일: CsvFormat.py 프로젝트: se210/tracy
  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()
예제 #12
0
파일: CsvFormat.py 프로젝트: se210/tracy
    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()
예제 #13
0
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
예제 #14
0
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
예제 #15
0
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
예제 #16
0
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
예제 #17
0
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
예제 #18
0
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()
예제 #19
0
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
예제 #20
0
파일: BinaryCodec.py 프로젝트: se210/tracy
  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()
예제 #21
0
 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
예제 #22
0
    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()
예제 #23
0
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
예제 #24
0
파일: CorePlugin.py 프로젝트: se210/tracy
  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)
예제 #25
0
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)
예제 #26
0
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)
예제 #27
0
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
예제 #28
0
    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()
예제 #29
0
파일: BinaryCodec1.py 프로젝트: se210/tracy
  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()
예제 #30
0
 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
예제 #31
0
    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)
예제 #33
0
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
예제 #34
0
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
예제 #35
0
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)
예제 #36
0
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)
예제 #37
0
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)
예제 #38
0
 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)))
예제 #39
0
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
예제 #40
0
    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
예제 #41
0
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
예제 #42
0
  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()
예제 #43
0
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)
예제 #44
0
    
  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
  
예제 #45
0
     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(
예제 #46
0
파일: GlesReport.py 프로젝트: se210/tracy
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()
예제 #47
0
파일: TextFormat.py 프로젝트: se210/tracy
    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()
예제 #48
0
 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])
예제 #49
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()
예제 #50
0
 def assign_task(self, task):
     '''增加作业'''
     self.tasks.put(Task.from_dict(task))
예제 #51
0
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
예제 #52
0
파일: CorePlugin.py 프로젝트: se210/tracy
    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)
예제 #53
0
  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
예제 #54
0
    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()
예제 #55
0
파일: TextFormat.py 프로젝트: se210/tracy
  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()
예제 #56
0
파일: Analyzer.py 프로젝트: se210/tracy
 def reload(self):
   task      = Task.startTask("reload", "Reloading plugins", len(sys.modules))
   for plugin in self.plugins:
     reload(sys.modules[plugin.__module__])