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