diff -r e375a7921169 -r 57c618273d5c fbs/fontandbitmapserver/utils/fbsresource_count.pl --- /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 = ; + + +## +## 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); +