fbs/fontandbitmapserver/utils/fbsresource_count.pl
changeset 160 969102054596
child 178 89bd4cfee505
equal deleted inserted replaced
138:7652d902218f 160:969102054596
       
     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