tracesrv/tracecompiler/internal/scripts/ost_metrics.pl
author hgs
Tue, 26 Oct 2010 16:20:32 +0300
changeset 62 1c2bb2fc7c87
permissions -rw-r--r--
201043

#
# Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved.
# This component and the accompanying materials are made available
# under the terms of "Eclipse Public License v1.0"
# which accompanies this distribution, and is available
# at the URL "http://www.eclipse.org/legal/epl-v10.html".
#
# Initial Contributors:
# Nokia Corporation - initial contribution.
#
# Contributors:
#
# Description: 
#
#!perl -w
# 
# 

#*********************************************************************
# ost_metrics.pl
# *********************************************************************
#
# VERSION     : 8      Draft         Feb-15-2010      Adrian Issott
# REASION     : Minor update to output style and added warnings about 
#               the tool being unsupported
#
# VERSION     : 7      Draft         Sep-16-2009      Adrian Issott
# REASION     : Added support for restricting output to specific
#               components
#
# VERSION     : 6      Draft         Sep-15-2009      Adrian Issott
# REASION     : Added support for older environments with dictionaries
#               under epoc32\include\internal\symbiantraces\dictionary
#
# VERSION     : 5      Draft         Sep-11-2009      Adrian Issott
# REASION     : Added trace name listing
#               Added counting of trace / group ID with lower case names
#               Made the output of detailed inforamtion optional 
#               Added support for epocroots other than \
#               Added warning about assuming epocroot=\ when it's not set
#               Fixed illegal division by zero issue when no components were found
#
# VERSION     : 4      Draft         Sep-11-2008      Esa Karvanen
# REASION     : Skip duplicate UID's when parsing
#
# VERSION     : 3      Draft         May-07-2008      Esa Karvanen
# REASION     : Changed to print amount of traces and stuff
#
# VERSION     : 2      Draft         May-06-2008      Esa Karvanen
# REASION     : Changed to calculate unique groups names
#
# VERSION     : 1      Draft         Mar-28-2008      Teemu Piiroinen
# REASION     : Initial version

use strict;
use warnings;
use env;

use Getopt::Long;
use Pod::Usage;

warn "\n";
warn "Warning: this script is not supported and the Dynamic Analysis Tools team\n";
warn "does NOT promise to fix any bugs or add any functionality to it.\n";
warn "\n";

my %options;
GetOptions('h|help|?'         => \$options{showHelp},
           'm|manual'         => \$options{showManual},
           'r|restrictTo=s'   => \$options{restrictTo},
           'c|byComponent'    => \$options{byComponent},
           't|showTraceNames' => \$options{showTraceNames},
           'l|lowerCaseNames' => \$options{lowerCaseNames},
  ) or pod2usage(-Verbose => 0);
pod2usage(-Verbose => 1) if ($options{showHelp});
pod2usage(-Verbose => 2) if ($options{showManual});

$options{byComponent} = 1 if $options{showTraceNames};

if (defined $options{restrictTo}) {
  eval "'' =~ /$options{restrictTo}/";
  die "Invalid restrictTo pattern ($options{restrictTo}): $@\n" if $@;    
} else {
  $options{restrictTo} = '.*';
}

my $component_count = 0;

my $group_count = 0;
my $total_group_count = 0;

my $trace_count = 0;
my $component_trace_count = 0;
my $total_trace_count = 0;
my @allgroups = ();
my %hashgroups = ();
my %uids;

my $lowerCaseGroupNames = 0;
my $lowerCaseTraceNames = 0;

my $epocroot;
if (not defined $ENV{EPOCROOT}) {
	warn "Warning: EPOCROOT not set so assuming it's \\\n";
	$epocroot = '\\';
} else {
	$epocroot = $ENV{EPOCROOT};
}
die "Expected the EPOCROOT ($epocroot) to be a directory\n" unless -d $epocroot;

my $ost_dictionaries_dir = $epocroot.'epoc32\ost_dictionaries';
print "Looking for dictionaries in $ost_dictionaries_dir ...\n";

if (not -d $ost_dictionaries_dir) {
   $ost_dictionaries_dir = $epocroot.'epoc32\include\internal\symbiantraces\dictionary';
   print "Looking for dictionaries in $ost_dictionaries_dir ...\n";
}
die "Couldn't find the OST dictionaries directory\n" unless -d $ost_dictionaries_dir;

print "Found the OST dictionaries directory\n";
print "\n";

my $dir_cmd = "dir $ost_dictionaries_dir\\*.xml /S 	/B 2>NUL";
my $dir_return = qx($dir_cmd);
my $current_group;

foreach my $file (split("\n", $dir_return))
{
	next unless $file =~ /$options{restrictTo}/i;
	
	# OST Autogen headers contain "_0x" in their file name
	if ($file =~ /_0x(.+?)_/i)
	{
		# Skip duplicate UID
		if (exists($uids{$1}))
		{
			warn "Warning: skipping duplicate UID in file " . $file . "\n";

		}
		# This UID for the first time, parse the file
		else
		{
			$uids{$1} = 0;
			parseFile($file);
		}
	}
	# Also calculate BTraceHooksDictionary
	elsif ($file =~ m/(BTraceHooksDictionary\.xml)/i)
	{
		parseFile($file);
	}
}

# Remove duplicates from the groups list
my %seen = ();
my @uniq_groups = ();
foreach my $item (@allgroups) {
  push(@uniq_groups, $item) unless $seen{$item}++;
}


### OUTPUT TOTALS ###


my @groupNames = sort keys %hashgroups; 
my $uniq_groups = scalar @groupNames;

my $avg_groups = ($component_count > 0 ? sprintf "%.2f",($total_group_count / $component_count) : 0);

print "\n\n--------------TOTALS--------------\n\n";
print "Component count: $component_count\n";
print "Unique group count: $uniq_groups\n";
print "Average groups per component: $avg_groups\n";
print "Trace count: $total_trace_count\n";

if ($options{lowerCaseNames}) {
	for my $groupName (@groupNames) {
		if (uc($groupName) ne $groupName) {
			$lowerCaseGroupNames++;
		} 
	
	}
	
	print "\n";
	print "Lower case Group ID names count: $lowerCaseGroupNames\n";
	print "Lower case Trace ID names count: $lowerCaseTraceNames\n";
}


### OUTPUT GROUP ID SUMMARY ###


# Generate new array where key is the amount of traces and value is the string to be printed
my @group_lines = ();
my $groupNo = 0;
foreach my $key (@groupNames) {
	my $line = "";
	
	# Check how many times this group can be found from all groups array
	my $occurrences = 0;
	foreach my $item (@allgroups) {
		if ($item eq $key) {
			$occurrences = $occurrences + 1;
		}
	}
	
	my $value = $hashgroups{$key};

	my $trace_percents = ($total_trace_count > 0 ? sprintf "%.2f",($value / $total_trace_count) * 100 : 0);	
	my $component_percents = ($component_count > 0 ? sprintf "%.2f",($occurrences / $component_count) * 100 : 0);

    # Add the group name
	my $i = 0;
	$line .= "$key";
    while ((length $key) + $i < 42){
    	$line .= " ";
    	$i = $i + 1;
    }

    # Add the number of traces  
    $i = 0;
    $line .= "$value";
    while ((length $value) + $i < 5){
    	$line .= " ";
  	  $i = $i + 1;
    }

    # Add the number of traces in percents
    $line .= "($trace_percents %)";
    $i = 0;
    while ((length $trace_percents) + $i < 21){
    	$line .= " ";
    	$i = $i + 1;
    }
  
    # Add used by no. of components
    $i = 0;
    $line .= "$occurrences";
    while ((length $occurrences) + $i < 3){
    	$line .= " ";
    	$i = $i + 1;
    }

    # Add used by no. of components in percents 
    $line .= "($component_percents %)\n";
  
    $group_lines[$groupNo][0] = $value;
    $group_lines[$groupNo][1] = $line;
    $groupNo = $groupNo + 1;
}

my @sorted_group_lines = reverse sort{$a->[0] <=> $b->[0]} @group_lines;  #if the $id'th column is numerically

print "\n\n--------------GROUP ID SUMMARY--------------\n\n";
print "GROUP NAME\t\t\t\tAMOUNT OF TRACES\tUSED BY NO. OF COMPONENTS\n\n";

foreach my $line (@sorted_group_lines) {
	print $$line[1];
}


#######################################################################
# Parses file
#######################################################################
sub parseFile
{
	
	my $file = $_[0];
	open FILE, "<$file" or die $!;

			foreach my $line (<FILE>)
			{
				if ($line =~ /<path val=\"(.+?)\"/i)
				{
					print "Path: $1\n" if $options{byComponent};
				}

				if ($line =~ /<component id=\"-?\d+\" name=\"(.+?)\"/i)
				{
					print "Component: $1\n" if $options{byComponent};

					$component_count++;
				}

				if ($line =~ /<group id=\"\d+\" name=\"(.+?)\"/i)
				{
					my $group = $1;
					print "\tGroup: $group\n" if $options{byComponent};
					push(@allgroups, $group);

					if (not defined $hashgroups{$group})
					{
						$hashgroups{$group} = 0;
					}

					$group_count++;
					$total_group_count++;
					$current_group = $group;
					
					print "\tGroup trace names:\n" if $options{showTraceNames};
				}

				if ($line =~ /<\/component>/i)
				{
					if ($options{byComponent}) {
						print "\tGroup count: $group_count\n";
						print "\tComponent trace count: $component_trace_count\n\n\n";
					}

					$group_count = 0;
					$component_trace_count = 0;
				}
				if ($line =~ /<trace data-ref=\"\d+\"(?:\s+name=\"(\w+)\")?/i)
				{
					if (defined $1) {
						print "\t\t$1\n" if $options{showTraceNames};
						if ($options{lowerCaseNames} and uc($1) ne $1) {
							$lowerCaseTraceNames++;
						}
					} 
					$trace_count++;
					$component_trace_count++;
					$total_trace_count++;
				}

				if ($line =~ /<\/group>/i)
				{
					print "\tGroup trace count: $trace_count\n" if $options{byComponent};
					$hashgroups{$current_group} = ($hashgroups{$current_group} + $trace_count);
					$trace_count = 0;
				}
			}

			close FILE;
}

warn "\n";
warn "Warning: this script is not supported and the Dynamic Analysis Tools team\n";
warn "does NOT promise to fix any bugs or add any functionality to it.\n";
warn "\n";

__END__

=head1 NAME

ost_metrics - Prints metrics about OST usage based on the dictionaries in an EPOCROOT

=head1 SYNOPSIS

ost_metrics [options]

=head1 OPTIONS

 -h (--help)             Brief help message.
 -m (--manual)           Full documentation.
 -r (--restrictTo) <re>  Restrict the output to just dictionaries with names 
                         matching the regular expression re.
 -c (--byComponent)      Output detailed information about the trace used in each 
                         component.
 -t (--showTraceNames)   Output detailed information about the trace ID names used.
                         Implies -byComponent
 -l (--lowerCaseNames)   Count the number of lower case names in the dictionaries.
 
=head1 DESCRIPTION

This script reads in the dictionaries found under EPOCROOT\epoc32\ost_dictionaries
and outputs the following information:

=over

=item 1 OST usage breakdown by component if --byComponent is specified

=item 2 OST trace ID usage by component if --showTraceNames is specified

=item 3 Group ID usage in the environment

=item 4 Total usage in the environment

=back

Note that if you don't define EPOCROOT this script assumes you mean "\". 

=head1 SUPPORT

Please note that this script is not supported and the Dynamic Analysis Tools team
does NOT promise to fix any bugs or add any functionality to it.

=head1 COPYRIGHT

Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.

=cut