sbsv2/raptor/bin/annofile.py
changeset 28 b8fa7dfeeaa1
equal deleted inserted replaced
27:3a31ca4b29c4 28:b8fa7dfeeaa1
       
     1 #
       
     2 # Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 # All rights reserved.
       
     4 # This component and the accompanying materials are made available
       
     5 # under the terms of the License "Eclipse Public License v1.0"
       
     6 # which accompanies this distribution, and is available
       
     7 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 #
       
     9 # Initial Contributors:
       
    10 # Nokia Corporation - initial contribution.
       
    11 #
       
    12 # Contributors:
       
    13 #
       
    14 # Description:  
       
    15 # Annofile class
       
    16 #
       
    17 
       
    18 import xml.sax
       
    19 import os
       
    20 
       
    21 class Annofile(xml.sax.handler.ContentHandler):
       
    22 	"""A class to represent an emake anno file"""
       
    23 
       
    24 	def __init__(self, name, maxagents=30):
       
    25 		self.name = name
       
    26 		self.overallAggregateTime = 0
       
    27 		self.duration = 0
       
    28 		self.inJob = False
       
    29 		self.inMetricDuration = False
       
    30 		self.jobType = ''
       
    31 		self.nodes = set()
       
    32 		self.maxagents = maxagents
       
    33 
       
    34 		parser = xml.sax.make_parser()
       
    35 		parser.setContentHandler(self)
       
    36 		try:
       
    37 			parser.parse(open(name))
       
    38 		except xml.sax._exceptions.SAXParseException, e:
       
    39 			print "Error:\n" + str(e)
       
    40 			print "Ignore that file, parsing continues..."
       
    41 
       
    42 	
       
    43 	def startElement(self, name, attrs):
       
    44 		if name == 'build':
       
    45 			# attrs.get() returns unicode type
       
    46 			self.cm = attrs.get('cm', '')
       
    47 					
       
    48 		elif name == 'job':
       
    49 			self.inJob = True
       
    50 			self.jobType = attrs.get('type', '')
       
    51 
       
    52 		elif name == 'timing':
       
    53 			# Find agent number
       
    54 			node = attrs.get('node')
       
    55 			if node not in self.nodes:
       
    56 				self.nodes.add(node)
       
    57 			
       
    58 			# Calculate aggregate build time
       
    59 			# This is the sum of time spending on each node
       
    60 			# Ideally it equals the build time if there is 
       
    61 			# only one node
       
    62 			time = float(attrs.get('completed')) \
       
    63 				- float(attrs.get('invoked'))
       
    64 			self.overallAggregateTime += time
       
    65 
       
    66 			# Calculate parse time
       
    67 			if self.inJob and self.jobType == 'parse':
       
    68 				self.parseTime = time
       
    69 
       
    70 		elif name == 'metric':
       
    71 			if attrs.get('name') == 'duration':
       
    72 				self.inMetricDuration = True
       
    73 			
       
    74 
       
    75 	def endElement(self, name):
       
    76 		if name == 'job':
       
    77 			self.inJob = False
       
    78 		elif name == 'metric':
       
    79 			if self.inMetricDuration:
       
    80 				self.inMetricDuration = False
       
    81 
       
    82 		# Parse to the end of XML file
       
    83 		elif name == 'build':
       
    84 			self.doFinal()
       
    85 	
       
    86 	def characters(self, ch):
       
    87 		if self.inMetricDuration:
       
    88 			self.duration = ch
       
    89 
       
    90 
       
    91 	# Get class attributes
       
    92 
       
    93 	def getParseTime(self):
       
    94 		"""Get the time that emake spends on 
       
    95 		parsing all makefiles
       
    96 		"""
       
    97 		return self.parseTime
       
    98 
       
    99 	def getOverallDuration(self):
       
   100 		"""Get the overall build duration"""
       
   101 		return float(self.duration)
       
   102 	
       
   103 	def getClusterManager(self):
       
   104 		return self.cm
       
   105 
       
   106 	def getAggregateTime(self):
       
   107 		"""This is the sum of time spending on each node.
       
   108 		Ideally it equals the build time if there is 
       
   109 		only one node
       
   110 		"""
       
   111 		return self.overallAggregateTime
       
   112 	
       
   113 	# Calculate two efficiencies: 
       
   114 	# first includes makefile parse time; second doesn't 
       
   115 	def getEfficiency(self):
       
   116 		"""100% means all nodes are busy from start to finish.
       
   117 		"""
       
   118 		at = self.getAggregateTime()
       
   119 		num = self.maxagents
       
   120 		d = self.getOverallDuration()
       
   121 		
       
   122 		idealDuration = at / num
       
   123 		if d != 0:
       
   124 			efficiency = round(idealDuration / d, 3)
       
   125 		else:	
       
   126 			efficiency = 0
       
   127 
       
   128 		# This is efficiency WITHOUT counting makefile
       
   129 		# parsing time.  Tempararily still useful.
       
   130 		pt = self.getParseTime()
       
   131 		idealD_wo = (at - pt) / num
       
   132 		if d != pt:
       
   133 			e_wo = round(idealD_wo / (d - pt), 3)
       
   134 		else:
       
   135 			e_wo = 0
       
   136 		
       
   137 		#return str(efficiency * 100) + '%', str(e_wo * 100) + '%'
       
   138 		return efficiency, e_wo
       
   139 
       
   140 	def doFinal(self):	
       
   141 		report = open('anno_report.xml', 'a')
       
   142 		report.write("<annofile name='%s'>\n" % self.name)	
       
   143 		report.write("<metric name='agentNumber' value='%s'/>\n" % len(self.nodes))
       
   144 		report.write("<metric name='makefileParseTime' value='%s'/>\n" \
       
   145 				% self.getParseTime())
       
   146 		report.write("<metric name='duration' value='%s'/>\n" \
       
   147 				% self.getOverallDuration())
       
   148 		report.write("<metric name='aggregateTime' value='%s'/>\n" \
       
   149 				% self.getAggregateTime())
       
   150 		report.write("<metric name='efficiency' value='%f'/>\n" \
       
   151 				% self.getEfficiency()[0])
       
   152 		report.write("<metric name='efficiencyNoMakefile' value='%f'/>\n" \
       
   153 				% self.getEfficiency()[1])
       
   154 		report.write("</annofile>\n")
       
   155 		report.close()
       
   156 
       
   157 	def __str__(self):
       
   158 		s = " <metric name='agentcount' value='%d' />\n" % len(self.nodes) + \
       
   159 			" <metric name='maxagents' value='%d' />\n" % self.maxagents + \
       
   160 			" <metric name='parsetimesecs' value='%s' />\n" % self.getParseTime() + \
       
   161 			" <metric name='overallduration' value='%s' />\n" % self.getOverallDuration() + \
       
   162 			" <metric name='aggregatetime' value='%s' />\n" % self.getAggregateTime() + \
       
   163 			" <metric name='efficiency' value='%s' />\n" % self.getEfficiency()[0] + \
       
   164 			" <metric name='efficiency_nomake' value='%s' />\n" % self.getEfficiency()[1] 
       
   165 
       
   166 		return s
       
   167 	
       
   168 
       
   169 
       
   170 if __name__ == '__main__':
       
   171 	
       
   172 	# Work around annoying DOCTYPE error by 
       
   173 	# creating a dummy DTD file	
       
   174 	if not os.path.exists('build.dtd'):
       
   175 		dummy = open('build.dtd', 'w')
       
   176 		dummy.close()
       
   177 
       
   178 	################## Edit this basepath ################
       
   179 	basepath = '92_7952_201022_logs\\output\\logs'
       
   180 	######################################################
       
   181 
       
   182 	# Find out all the annofiles
       
   183 	annofiles = []
       
   184 	for dirpath, dirs, files in os.walk(basepath):
       
   185 		for f in files:
       
   186 			if f.endswith('.anno') or f.endswith('.anno.xml'):
       
   187 				annofiles.append(dirpath + '\\' + f)
       
   188 
       
   189 	#print annofiles # debug
       
   190 	
       
   191 	# Parse all the annofiles and generate report
       
   192 	# Write XML header
       
   193 	report = open('anno_report.xml', 'w')
       
   194 	report.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n')
       
   195 	report.write("<report>\n")
       
   196 	report.close()
       
   197 	# Parse each annofile
       
   198 	#num = 0 # debug
       
   199 	parser = xml.sax.make_parser()
       
   200 	for afilename in annofiles:
       
   201 		parser.setContentHandler(Annofile(afilename))
       
   202 		try:
       
   203 			parser.parse(open(afilename))
       
   204 		except xml.sax._exceptions.SAXParseException, e:
       
   205 			print "Error:\n" + str(e)
       
   206 			print "Ignore that file, parsing continues..."
       
   207 			
       
   208 		#num += 1 # <debug> only process num annofiles
       
   209 		#if num == 3:
       
   210 		#	break
       
   211 
       
   212 	# Write XML footer
       
   213 	report = open('anno_report.xml', 'a')
       
   214 	report.write("</report>")
       
   215 	report.close()
       
   216