fbs/fontandbitmapserver/utils/fbsresource_count.pl
branchRCL_3
changeset 18 57c618273d5c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/utils/fbsresource_count.pl	Thu Aug 19 11:11:18 2010 +0300
@@ -0,0 +1,270 @@
+#!/usr/local/bin/perl
+#
+# 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:
+#  This script parses trace data produced by OST from FBS, using the the FBSCLI, 
+#  FBSERV and Symbian BTrace Hooks OST dictionaries, to produce a CSV output of
+#  the amount of FBS resources used per-thread over a user-definable time
+#  granularity, since the start of the trace.
+# 
+#  To use, enable SYMBIAN_KERNEL_THREAD_IDENTIFICATION trace group in Symbian
+#  BTrace Hooks OST dictionary, GRAPHICS_RESOURCE_MANAGEMENT_SEMANTICS in FBSERV
+#  OST dictionary, and GRAPHICS_RESOURCE_MANAGEMENT_SEMANTICS, 
+#  GRAPHICS_RESOURCE_MANAGEMENT_FUNCTIONS and GRAPHICS_CONTROL_FUNCTIONS in
+#  FBSCLI OST dictionary. Once tracing is gathered, save trace output as ascii 
+#  and run this script against it. The resulting file can then be imported into
+#  a spreadsheet application to be visually processed.
+#  
+#  KNOWN DEFECTS:
+#  Once the log time goes beyond midnight, snapshots will stop being taken.
+#
+
+use strict;
+
+# Sanity checking of the command line parameters...
+if ($#ARGV == -1 || $ARGV[0] eq "help" || $ARGV[0] eq "/?")
+{
+   print "\nusage: $0 filename [-h]\n";
+   print "where\n";
+   print " -h : Specifies the heartbeat in millisecs (default=10000)\n";
+   exit;
+}
+
+
+## Modifiable constants...
+my $CSV_DELIMITER = ',';
+
+# Time after start to take first snapshot, in millisecs
+my $firstHeartBeatTimeMS = 1000;
+
+# Default heartbeat in millisecs if none specified.
+my $heartBeatMS = 10000;
+
+
+##
+## Internal structures...
+##
+my $heartBeatCount = 0;
+my $nextHeartBeatMS = -1;
+
+# Hash of FbsSessions to thread IDs.
+my %SessionThreadMap = ();
+
+# A hash of thread names to the fbs resource count.
+my %fbsResourcesPerThread = ();
+
+# Array of the above hashes, one hash per heartbeat.
+my @arrayOfSnapshots;
+
+# Hashes of thread and process names to IDs.
+my %ThreadNames;
+my %ProcessNames;
+
+
+##
+## Command line options parsing...
+## First arg is assumed to be the filename.
+##
+for my $i (1..$#ARGV)
+{
+   my $cma = $ARGV[$i];
+   if ($cma =~ m/-h(\d*)/)
+   {
+      $heartBeatMS = $1;
+   }
+   else
+   {
+      print "Unrecognised parameter: $cma , ignoring...\n";
+   }
+}
+
+## Read from the file.
+## Read the log into an array line by line.
+my $TRACE_FILENAME = $ARGV[0];
+open(INPUT_FILE, $TRACE_FILENAME) or die $!;
+my @traceLines = <INPUT_FILE>;
+
+
+##
+## Parse each line sequentially...
+##
+foreach my $line (@traceLines)
+{
+   my $timeFromMidnightMS;
+
+   ## 
+   ## If this line is about a new process, make a note of the name and the
+   ## associated process id, so that FbsSessions can be mapped to their 
+   ## thread by name.
+   ##
+   if ($line =~ /^.*Thread:Process name assigned;NThread:(.*);DProcess:(.*);Name:(.*)$/i)
+   {
+      my $threadId  = $1;
+      my $processId = $2;
+      my $processName = $3;
+      $ProcessNames{$processId} = $processName ;
+   }
+
+   ## 
+   ## If this line is about a new process, make a note of the name and the
+   ## associated process id, so that FbsSessions can be mapped to their 
+   ## thread by name when the csv is generated.
+   ##
+   if (($line =~ /^.*Thread:Thread created;NThread:(.*);DProcess:(.*);Name:(.*)$/i) ||
+      ($line =~ /^.*Thread:Thread name assigned;NThread:(.*);DProcess:(.*);Name:(.*)$/i))
+      {
+      my $threadId  = $1;
+      my $processId = $2;
+      my $threadName = $3;
+      my $fullThreadName = $ProcessNames{$processId} . ":" . $threadName;
+      $ThreadNames{$threadId} = $fullThreadName;
+   }
+
+   ##
+   ## Determine timestamp. If this time is beyond the heartbeat, 
+   ## take a snapshot and 
+   ##
+   if ($line =~ /^(\d\d):(\d\d):(\d\d)\.(\d{3})/)
+   {
+      $timeFromMidnightMS = ((($1 * 3600) + ($2 * 60) + $3) * 1000) + $4;
+      # Set up the time for the first snapshot.
+      if ($nextHeartBeatMS == -1) 
+      {
+         $nextHeartBeatMS = $timeFromMidnightMS + $firstHeartBeatTimeMS;
+      }
+   }
+
+   ##
+   ## If heartbeat reached, take snapshot of bmp memory per thread
+   ## and set next heartbeat time.
+   ##
+   while ($timeFromMidnightMS >= $nextHeartBeatMS)
+   {
+      $nextHeartBeatMS += $heartBeatMS;
+      # take a snapshot of the current bitmap memory usage per thread
+      while ((my $thread, my $fbsResourceCount) = each(%fbsResourcesPerThread))
+      {
+           $arrayOfSnapshots[$heartBeatCount]{$thread} = $fbsResourceCount;
+      }
+      $heartBeatCount++;
+   }
+
+   ## FBS Client-side traces.
+   if ($line =~ m/\tFBSCLI: /)
+   {
+      ##
+      ## If this line is an FBSCLI trace, and it contains iSSH then
+      ## it gives a chance to map a client thread ID to a session handle.
+      ## 
+      if ( $line =~ m/iSSH=(\w*);.*Thread ID:(.*)$/)
+      {
+         my $ServerSessionHandle = $1;
+         my $thread = $2;
+         if ($thread ne "0x00000000")
+         {
+            $SessionThreadMap{$ServerSessionHandle} = $thread;
+         }
+      }
+   }
+
+   ## 
+   ## FBS Server-side traces.
+   ##
+   if ($line =~ m/\tFBSERV: /)
+   {
+      ## The line must have a s= parameter to be useful - the session server handle.
+      ## Any FBSERV line without this is not considered for parsing.
+      if ($line =~ m/; iSSH=(\w*);/)
+      {
+         my $FbsSessionHandle = $1;
+         my $thread = "Unknown Thread [Session=$FbsSessionHandle]";
+         if (defined($SessionThreadMap{$FbsSessionHandle}))
+         {
+            $thread = $SessionThreadMap{$FbsSessionHandle};
+         }
+         if ($line =~ m/; rc=(\d+);/)
+         {
+            my $resourceCount = $1;
+            if ($resourceCount == 0)
+            { 
+               $resourceCount = '';
+            }
+            $fbsResourcesPerThread{$thread} = $resourceCount;
+         }
+      }
+   }
+}
+
+close (INPUT_FILE);
+
+
+##
+## Make a map of unique threads across all snapshots
+## This is so only one occurrence of each thread will appear
+## in the csv file.
+##
+my %uniqueThreads = ();
+for my $i (0..$#arrayOfSnapshots)
+{
+   for my $thread (keys %{$arrayOfSnapshots[$i]})
+   {
+      $uniqueThreads{$thread} = 1;
+   }
+}
+
+##
+## Start writing to file.
+## First row, which contains the heartbeat number column headings...
+##
+my $OUTPUT_FILENAME = sprintf("%s.csv", $TRACE_FILENAME);
+open(OUTPUT_FILE,">$OUTPUT_FILENAME") or die $!;
+print OUTPUT_FILE "Session$CSV_DELIMITER";
+for my $i (0..$heartBeatCount)
+{
+    print OUTPUT_FILE "$i$CSV_DELIMITER";
+}
+
+##
+## For each subsequent row, print the first thread and the
+## memory at each snapshot...
+##
+print OUTPUT_FILE "\n";
+while ((my $thread, my $dummy) = each(%uniqueThreads))
+{
+    # Resolve the thread to its full name...
+    print OUTPUT_FILE "$thread";
+    if (defined($ThreadNames{$thread}) )
+    {
+       my $threadName = $ThreadNames{$thread};
+       print OUTPUT_FILE ":$threadName";
+    }
+    print OUTPUT_FILE "$CSV_DELIMITER";
+
+    # print the memory use per thread, for each snapshot...
+    for my $i (0..$#arrayOfSnapshots)
+    {
+       my %snapshot = %{$arrayOfSnapshots[$i]};
+       while ((my $snapshotThread, my $fbsResourceCount) = each(%snapshot))
+       {
+           if ($snapshotThread eq $thread) 
+           {
+              print OUTPUT_FILE "$fbsResourceCount";
+           }
+       }
+       print OUTPUT_FILE "$CSV_DELIMITER";
+    }
+    print OUTPUT_FILE "\n";
+}
+close (OUTPUT_FILE);
+