os/graphics/fbs/fontandbitmapserver/utils/fbsresource_count.pl
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 #!/usr/local/bin/perl
     2 #
     3 # Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
     4 # All rights reserved.
     5 # This component and the accompanying materials are made available
     6 # under the terms of "Eclipse Public License v1.0"
     7 # which accompanies this distribution, and is available
     8 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
     9 #
    10 # Initial Contributors:
    11 # Nokia Corporation - initial contribution.
    12 #
    13 # Contributors:
    14 #
    15 # Description:
    16 #  This script parses trace data produced by OST from FBS, using the the FBSCLI, 
    17 #  FBSERV and Symbian BTrace Hooks OST dictionaries, to produce a CSV output of
    18 #  the amount of FBS resources used per-thread over a user-definable time
    19 #  granularity, since the start of the trace.
    20 # 
    21 #  To use, enable SYMBIAN_KERNEL_THREAD_IDENTIFICATION trace group in Symbian
    22 #  BTrace Hooks OST dictionary, GRAPHICS_RESOURCE_MANAGEMENT_SEMANTICS in FBSERV
    23 #  OST dictionary, and GRAPHICS_RESOURCE_MANAGEMENT_SEMANTICS, 
    24 #  GRAPHICS_RESOURCE_MANAGEMENT_FUNCTIONS and GRAPHICS_CONTROL_FUNCTIONS in
    25 #  FBSCLI OST dictionary. Once tracing is gathered, save trace output as ascii 
    26 #  and run this script against it. The resulting file can then be imported into
    27 #  a spreadsheet application to be visually processed.
    28 #  
    29 #  KNOWN DEFECTS:
    30 #  Once the log time goes beyond midnight, snapshots will stop being taken.
    31 #
    32 
    33 use strict;
    34 
    35 # Sanity checking of the command line parameters...
    36 if ($#ARGV == -1 || $ARGV[0] eq "help" || $ARGV[0] eq "/?")
    37 {
    38    print "\nusage: $0 filename [-h]\n";
    39    print "where\n";
    40    print " -h : Specifies the heartbeat in millisecs (default=10000)\n";
    41    exit;
    42 }
    43 
    44 
    45 ## Modifiable constants...
    46 my $CSV_DELIMITER = ',';
    47 
    48 # Time after start to take first snapshot, in millisecs
    49 my $firstHeartBeatTimeMS = 1000;
    50 
    51 # Default heartbeat in millisecs if none specified.
    52 my $heartBeatMS = 10000;
    53 
    54 
    55 ##
    56 ## Internal structures...
    57 ##
    58 my $heartBeatCount = 0;
    59 my $nextHeartBeatMS = -1;
    60 
    61 # Hash of FbsSessions to thread IDs.
    62 my %SessionThreadMap = ();
    63 
    64 # A hash of thread names to the fbs resource count.
    65 my %fbsResourcesPerThread = ();
    66 
    67 # Array of the above hashes, one hash per heartbeat.
    68 my @arrayOfSnapshots;
    69 
    70 # Hashes of thread and process names to IDs.
    71 my %ThreadNames;
    72 my %ProcessNames;
    73 
    74 
    75 ##
    76 ## Command line options parsing...
    77 ## First arg is assumed to be the filename.
    78 ##
    79 for my $i (1..$#ARGV)
    80 {
    81    my $cma = $ARGV[$i];
    82    if ($cma =~ m/-h(\d*)/)
    83    {
    84       $heartBeatMS = $1;
    85    }
    86    else
    87    {
    88       print "Unrecognised parameter: $cma , ignoring...\n";
    89    }
    90 }
    91 
    92 ## Read from the file.
    93 ## Read the log into an array line by line.
    94 my $TRACE_FILENAME = $ARGV[0];
    95 open(INPUT_FILE, $TRACE_FILENAME) or die $!;
    96 my @traceLines = <INPUT_FILE>;
    97 
    98 
    99 ##
   100 ## Parse each line sequentially...
   101 ##
   102 foreach my $line (@traceLines)
   103 {
   104    my $timeFromMidnightMS;
   105 
   106    ## 
   107    ## If this line is about a new process, make a note of the name and the
   108    ## associated process id, so that FbsSessions can be mapped to their 
   109    ## thread by name.
   110    ##
   111    if ($line =~ /^.*Thread:Process name assigned;NThread:(.*);DProcess:(.*);Name:(.*)$/i)
   112    {
   113       my $threadId  = $1;
   114       my $processId = $2;
   115       my $processName = $3;
   116       $ProcessNames{$processId} = $processName ;
   117    }
   118 
   119    ## 
   120    ## If this line is about a new process, make a note of the name and the
   121    ## associated process id, so that FbsSessions can be mapped to their 
   122    ## thread by name when the csv is generated.
   123    ##
   124    if (($line =~ /^.*Thread:Thread created;NThread:(.*);DProcess:(.*);Name:(.*)$/i) ||
   125       ($line =~ /^.*Thread:Thread name assigned;NThread:(.*);DProcess:(.*);Name:(.*)$/i))
   126       {
   127       my $threadId  = $1;
   128       my $processId = $2;
   129       my $threadName = $3;
   130       my $fullThreadName = $ProcessNames{$processId} . ":" . $threadName;
   131       $ThreadNames{$threadId} = $fullThreadName;
   132    }
   133 
   134    ##
   135    ## Determine timestamp. If this time is beyond the heartbeat, 
   136    ## take a snapshot and 
   137    ##
   138    if ($line =~ /^(\d\d):(\d\d):(\d\d)\.(\d{3})/)
   139    {
   140       $timeFromMidnightMS = ((($1 * 3600) + ($2 * 60) + $3) * 1000) + $4;
   141       # Set up the time for the first snapshot.
   142       if ($nextHeartBeatMS == -1) 
   143       {
   144          $nextHeartBeatMS = $timeFromMidnightMS + $firstHeartBeatTimeMS;
   145       }
   146    }
   147 
   148    ##
   149    ## If heartbeat reached, take snapshot of bmp memory per thread
   150    ## and set next heartbeat time.
   151    ##
   152    while ($timeFromMidnightMS >= $nextHeartBeatMS)
   153    {
   154       $nextHeartBeatMS += $heartBeatMS;
   155       # take a snapshot of the current bitmap memory usage per thread
   156       while ((my $thread, my $fbsResourceCount) = each(%fbsResourcesPerThread))
   157       {
   158            $arrayOfSnapshots[$heartBeatCount]{$thread} = $fbsResourceCount;
   159       }
   160       $heartBeatCount++;
   161    }
   162 
   163    ## FBS Client-side traces.
   164    if ($line =~ m/\tFBSCLI: /)
   165    {
   166       ##
   167       ## If this line is an FBSCLI trace, and it contains iSSH then
   168       ## it gives a chance to map a client thread ID to a session handle.
   169       ## 
   170       if ( $line =~ m/iSSH=(\w*);.*Thread ID:(.*)$/)
   171       {
   172          my $ServerSessionHandle = $1;
   173          my $thread = $2;
   174          if ($thread ne "0x00000000")
   175          {
   176             $SessionThreadMap{$ServerSessionHandle} = $thread;
   177          }
   178       }
   179    }
   180 
   181    ## 
   182    ## FBS Server-side traces.
   183    ##
   184    if ($line =~ m/\tFBSERV: /)
   185    {
   186       ## The line must have a s= parameter to be useful - the session server handle.
   187       ## Any FBSERV line without this is not considered for parsing.
   188       if ($line =~ m/; iSSH=(\w*);/)
   189       {
   190          my $FbsSessionHandle = $1;
   191          my $thread = "Unknown Thread [Session=$FbsSessionHandle]";
   192          if (defined($SessionThreadMap{$FbsSessionHandle}))
   193          {
   194             $thread = $SessionThreadMap{$FbsSessionHandle};
   195          }
   196          if ($line =~ m/; rc=(\d+);/)
   197          {
   198             my $resourceCount = $1;
   199             if ($resourceCount == 0)
   200             { 
   201                $resourceCount = '';
   202             }
   203             $fbsResourcesPerThread{$thread} = $resourceCount;
   204          }
   205       }
   206    }
   207 }
   208 
   209 close (INPUT_FILE);
   210 
   211 
   212 ##
   213 ## Make a map of unique threads across all snapshots
   214 ## This is so only one occurrence of each thread will appear
   215 ## in the csv file.
   216 ##
   217 my %uniqueThreads = ();
   218 for my $i (0..$#arrayOfSnapshots)
   219 {
   220    for my $thread (keys %{$arrayOfSnapshots[$i]})
   221    {
   222       $uniqueThreads{$thread} = 1;
   223    }
   224 }
   225 
   226 ##
   227 ## Start writing to file.
   228 ## First row, which contains the heartbeat number column headings...
   229 ##
   230 my $OUTPUT_FILENAME = sprintf("%s.csv", $TRACE_FILENAME);
   231 open(OUTPUT_FILE,">$OUTPUT_FILENAME") or die $!;
   232 print OUTPUT_FILE "Session$CSV_DELIMITER";
   233 for my $i (0..$heartBeatCount)
   234 {
   235     print OUTPUT_FILE "$i$CSV_DELIMITER";
   236 }
   237 
   238 ##
   239 ## For each subsequent row, print the first thread and the
   240 ## memory at each snapshot...
   241 ##
   242 print OUTPUT_FILE "\n";
   243 while ((my $thread, my $dummy) = each(%uniqueThreads))
   244 {
   245     # Resolve the thread to its full name...
   246     print OUTPUT_FILE "$thread";
   247     if (defined($ThreadNames{$thread}) )
   248     {
   249        my $threadName = $ThreadNames{$thread};
   250        print OUTPUT_FILE ":$threadName";
   251     }
   252     print OUTPUT_FILE "$CSV_DELIMITER";
   253 
   254     # print the memory use per thread, for each snapshot...
   255     for my $i (0..$#arrayOfSnapshots)
   256     {
   257        my %snapshot = %{$arrayOfSnapshots[$i]};
   258        while ((my $snapshotThread, my $fbsResourceCount) = each(%snapshot))
   259        {
   260            if ($snapshotThread eq $thread) 
   261            {
   262               print OUTPUT_FILE "$fbsResourceCount";
   263            }
   264        }
   265        print OUTPUT_FILE "$CSV_DELIMITER";
   266     }
   267     print OUTPUT_FILE "\n";
   268 }
   269 close (OUTPUT_FILE);
   270