os/graphics/fbs/fontandbitmapserver/utils/fbsbitmap_memory.pl
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 bitmap memory 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 # A hash of thread names to the amount of bitmap memory they 
    62 # have used since the start of the trace.
    63 my %bmpMemoryPerThread = ();
    64 
    65 # A hash of bitmaps fully qualified by the session they belong to,
    66 # and their local handle (because bitmaps can have the same local
    67 # handle in different threads), mapped to their size in bytes.
    68 my %bmpMemoryByServerHandle = ();
    69 
    70 # Hash of FbsSessions to thread IDs.
    71 my %SessionThreadMap = ();
    72 
    73 # Array of the above hashes, one hash per heartbeat.
    74 my @arrayOfSnapshots;
    75 
    76 # Hashes of thread and process names to IDs.
    77 my %ThreadNames;
    78 my %ProcessNames;
    79 
    80 
    81 ##
    82 ## Command line options parsing...
    83 ## First arg is assumed to be the filename.
    84 ##
    85 for my $i (1..$#ARGV)
    86 {
    87    my $cma = $ARGV[$i];
    88    if ($cma =~ m/-h(\d*)/)
    89    {
    90       $heartBeatMS = $1;
    91    }
    92    else
    93    {
    94       print "Unrecognised parameter: $cma , ignoring...\n";
    95    }
    96 }
    97 
    98 ## Read from the file.
    99 ## Read the log into an array line by line.
   100 my $TRACE_FILENAME = $ARGV[0];
   101 open(INPUT_FILE, $TRACE_FILENAME) or die $!;
   102 my @traceLines = <INPUT_FILE>;
   103 
   104 
   105 ##
   106 ## Parse each line sequentially...
   107 ##
   108 foreach my $line (@traceLines)
   109 {
   110    my $timeFromMidnightMS;
   111 
   112    ## 
   113    ## If this line is about a new process, make a note of the name and the
   114    ## associated process id, so that FbsSessions can be mapped to their 
   115    ## thread by name.
   116    ##
   117    if ($line =~ /^.*Thread:Process name assigned;NThread:(.*);DProcess:(.*);Name:(.*)$/i)
   118    {
   119       my $threadId  = $1;
   120       my $processId = $2;
   121       my $processName = $3;
   122       $ProcessNames{$processId} = $processName ;
   123    }
   124 
   125    ## 
   126    ## If this line is about a new process, make a note of the name and the
   127    ## associated process id, so that FbsSessions can be mapped to their 
   128    ## thread by name when the csv is generated.
   129    ##
   130    if (($line =~ /^.*Thread:Thread created;NThread:(.*);DProcess:(.*);Name:(.*)$/i) ||
   131       ($line =~ /^.*Thread:Thread name assigned;NThread:(.*);DProcess:(.*);Name:(.*)$/i))
   132       {
   133       my $threadId  = $1;
   134       my $processId = $2;
   135       my $threadName = $3;
   136       my $fullThreadName = $ProcessNames{$processId} . ":" . $threadName;
   137       $ThreadNames{$threadId} = $fullThreadName;
   138    }
   139 
   140    ##
   141    ## Determine timestamp. If this time is beyond the heartbeat, 
   142    ## take a snapshot and 
   143    ##
   144    if ($line =~ /^(\d\d):(\d\d):(\d\d)\.(\d{3})/)
   145    {
   146       $timeFromMidnightMS = ((($1 * 3600) + ($2 * 60) + $3) * 1000) + $4;
   147       # Set up the time for the first snapshot.
   148       if ($nextHeartBeatMS == -1) 
   149       {
   150          $nextHeartBeatMS = $timeFromMidnightMS + $firstHeartBeatTimeMS;
   151       }
   152    }
   153 
   154    ##
   155    ## If heartbeat reached, take snapshot of bmp memory per thread
   156    ## and set next heartbeat time.
   157    ##
   158    while ($timeFromMidnightMS >= $nextHeartBeatMS)
   159    {
   160       $nextHeartBeatMS += $heartBeatMS;
   161       # take a snapshot of the current bitmap memory usage per thread
   162       while ((my $thread, my $bmpMemory) = each(%bmpMemoryPerThread))
   163       {
   164            $arrayOfSnapshots[$heartBeatCount]{$thread} = $bmpMemory;
   165       }
   166       $heartBeatCount++;
   167    }
   168 
   169    ## FBS Client-side traces.
   170    if ($line =~ m/\tFBSCLI: /)
   171    {
   172       ##
   173       ## If this line is an FBSCLI trace, and it contains iSSH then
   174       ## it gives a chance to map a client thread ID to a session handle.
   175       ## 
   176       if ( $line =~ m/iSSH=(\w*);.*Thread ID:(.*)$/)
   177       {
   178          my $ServerSessionHandle = $1;
   179          my $thread = $2;
   180          if ($thread ne "0x00000000")
   181          {
   182             $SessionThreadMap{$ServerSessionHandle} = $thread;
   183          }
   184       }
   185    }
   186 
   187    ## 
   188    ## FBS Server-side traces.
   189    ##
   190    if ($line =~ m/\tFBSERV: /)
   191    {
   192       ## The line must have a s= parameter to be useful - the session server handle.
   193       ## Any FBSERV line without this is not considered for parsing.
   194       if ($line =~ m/; iSSH=(\w*);/)
   195       {
   196          my $FbsSessionHandle = $1;
   197          my $thread = "Unknown Thread [Session=$FbsSessionHandle]";
   198          if (defined($SessionThreadMap{$FbsSessionHandle}))
   199          {
   200             $thread = $SessionThreadMap{$FbsSessionHandle};
   201          }
   202          if ($line =~ m/# Server resource destroyed; .*iH=(\w*);/)
   203          {
   204             my $bmpHandle = $1;
   205             my $bmpIdentifier = "$FbsSessionHandle:$bmpHandle";
   206             if (defined($bmpMemoryByServerHandle{$bmpIdentifier}))
   207             {
   208                $bmpMemoryPerThread{$thread} -= $bmpMemoryByServerHandle{$bmpIdentifier};
   209                delete $bmpMemoryByServerHandle{$bmpIdentifier};
   210             }
   211          }
   212          if ($line =~ m/# Server bitmap resized; .*iOldH=(\w*); iNewH=(\w*); newbytes=(\d*);/)
   213          {
   214             # When a bitmap is resized, the amount of memory held by the bitmap may change
   215             # and the bitmap localhandle will change.
   216             my $oldBmpHandle = $1;
   217             my $newBmpHandle = $2;
   218             my $newBmpBytes = $3;
   219             my $oldBmpIdentifier = "$FbsSessionHandle:$oldBmpHandle";
   220             my $newBmpIdentifier = "$FbsSessionHandle:$newBmpHandle";
   221             if (defined($bmpMemoryByServerHandle{$oldBmpIdentifier}))
   222             {
   223                $bmpMemoryPerThread{$thread} -= $bmpMemoryByServerHandle{$oldBmpIdentifier};
   224                delete $bmpMemoryByServerHandle{$oldBmpIdentifier};
   225             }
   226             $bmpMemoryPerThread{$thread} += $newBmpBytes;
   227             $bmpMemoryByServerHandle{$newBmpIdentifier} = $newBmpBytes;           
   228          }
   229          elsif ($line =~ m/#.*iOldH=(\w*); iNewH=(\w*);/)
   230          {
   231             # When a bitmap is compressed, cleaned or resized, the bitmap local handle changes
   232             my $oldBmpHandle = $1;
   233             my $newBmpHandle = $2;
   234             my $oldBmpIdentifier = "$FbsSessionHandle:$oldBmpHandle";
   235             my $newBmpIdentifier = "$FbsSessionHandle:$newBmpHandle";
   236             if (defined($bmpMemoryByServerHandle{$oldBmpIdentifier}))
   237             {
   238                my $bytes = $bmpMemoryByServerHandle{$oldBmpIdentifier};
   239                delete $bmpMemoryByServerHandle{$oldBmpIdentifier};
   240                $bmpMemoryByServerHandle{$newBmpIdentifier} = $bytes;
   241             }
   242          }
   243          elsif ($line =~ m/#.*iH=(\w*);.*bytes=(\d+);/)
   244          {
   245             # Duplication of a bitmap typically. When a bitmap is duplicated,
   246             # the memory is 'owned' by all threads that duplicate it.
   247             my $bmpHandle = $1;
   248             my $bmpBytes = $2;
   249             my $bmpIdentifier = "$FbsSessionHandle:$bmpHandle";
   250             $bmpMemoryPerThread{$thread} += $bmpBytes;
   251             $bmpMemoryByServerHandle{$bmpIdentifier} = $bmpBytes;
   252          }
   253       }
   254    }
   255 }
   256 
   257 close (INPUT_FILE);
   258 
   259 
   260 ##
   261 ## Make a map of unique threads across all snapshots
   262 ## This is so only one occurrence of each thread will appear
   263 ## in the csv file.
   264 ##
   265 my %uniqueThreads = ();
   266 for my $i (0..$#arrayOfSnapshots)
   267 {
   268    for my $thread (keys %{$arrayOfSnapshots[$i]})
   269    {
   270       $uniqueThreads{$thread} = 1;
   271    }
   272 }
   273 
   274 ##
   275 ## Start writing to file.
   276 ## First row, which contains the heartbeat number column headings...
   277 ##
   278 my $OUTPUT_FILENAME = sprintf("%s.csv", $TRACE_FILENAME);
   279 open(OUTPUT_FILE,">$OUTPUT_FILENAME") or die $!;
   280 print OUTPUT_FILE "Session$CSV_DELIMITER";
   281 for my $i (0..$heartBeatCount)
   282 {
   283     print OUTPUT_FILE "$i$CSV_DELIMITER";
   284 }
   285 
   286 ##
   287 ## For each subsequent row, print the first thread and the
   288 ## memory at each snapshot...
   289 ##
   290 print OUTPUT_FILE "\n";
   291 while ((my $thread, my $dummy) = each(%uniqueThreads))
   292 {
   293     # Resolve the thread to its full name...
   294     print OUTPUT_FILE "$thread";
   295     if (defined($ThreadNames{$thread}) )
   296     {
   297        my $threadName = $ThreadNames{$thread};
   298        print OUTPUT_FILE ":$threadName";
   299     }
   300     print OUTPUT_FILE "$CSV_DELIMITER";
   301 
   302     # print the memory use per thread, for each snapshot...
   303     for my $i (0..$#arrayOfSnapshots)
   304     {
   305        my %snapshot = %{$arrayOfSnapshots[$i]};
   306        while ((my $snapshotThread, my $bmpMemory) = each(%snapshot))
   307        {
   308            if ($snapshotThread eq $thread) 
   309            {
   310               print OUTPUT_FILE "$bmpMemory";
   311            }
   312        }
   313        print OUTPUT_FILE "$CSV_DELIMITER";
   314     }
   315     print OUTPUT_FILE "\n";
   316 }
   317 close (OUTPUT_FILE);
   318