kerneltest/e32utils/analyse/distribution.cpp
changeset 9 96e5fb8b040d
equal deleted inserted replaced
-1:000000000000 9:96e5fb8b040d
       
     1 // Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "analyse.h"
       
    17 #include "distribution.h"
       
    18 #include "output.h"
       
    19 
       
    20 #ifdef __MSVCDOTNET__
       
    21 #include <ostream>
       
    22 #include <iomanip>
       
    23 #else //!__MSVCDOTNET__
       
    24 #include <ostream.h>
       
    25 #include <iomanip.h>
       
    26 #endif //__MSVCDOTNET__
       
    27 
       
    28 #include <algorithm>
       
    29 
       
    30 // class Distribution
       
    31 
       
    32 namespace {
       
    33 
       
    34 int* BucketBox(int aSize)
       
    35 	{
       
    36 	int* buckets = new int[aSize];
       
    37 	memset(buckets, 0, sizeof(int) * aSize);
       
    38 	return buckets;
       
    39 	}
       
    40 
       
    41 class BucketTotals
       
    42 	{
       
    43 private:
       
    44 	class Generator
       
    45 		{
       
    46 	public:
       
    47 		inline Generator()
       
    48 			:iValue(0)
       
    49 			{}
       
    50 		inline int operator()()
       
    51 			{return iValue++;}
       
    52 	private:
       
    53 		int iValue;
       
    54 		};
       
    55 	class Sorter
       
    56 		{
       
    57 	public:
       
    58 		inline Sorter(const int* aTotals)
       
    59 			:iTotals(aTotals)
       
    60 			{}
       
    61 		inline bool operator()(int aLhs, int aRhs) const
       
    62 			{return (iTotals[aLhs] > iTotals[aRhs]);}
       
    63 	private:
       
    64 		const int* iTotals;
       
    65 		};
       
    66 public:
       
    67 	BucketTotals(Distribution::Data& aData, int aSize);
       
    68 	~BucketTotals();
       
    69 	void Sort();
       
    70 //
       
    71 	inline int Total() const;
       
    72 	inline int Map(int aBucket) const;
       
    73 	inline int operator[](int aBucket) const;
       
    74 	inline Result Sample(int aSample) const;
       
    75 private:
       
    76 	void Total(Distribution::Data& aData);
       
    77 private:
       
    78 	int iSize;
       
    79 	int* iTotals;
       
    80 	int* iOrdering;
       
    81 	int iTotal;
       
    82 	};
       
    83 
       
    84 BucketTotals::BucketTotals(Distribution::Data& aData, int aSize)
       
    85 	:iSize(aSize), iTotals(BucketBox(aSize)), iOrdering(BucketBox(aSize))
       
    86 	{
       
    87 	Total(aData);
       
    88 	std::generate_n(iOrdering, iSize, Generator());
       
    89 	}
       
    90 
       
    91 BucketTotals::~BucketTotals()
       
    92 	{
       
    93 	delete [] iTotals;
       
    94 	delete [] iOrdering;
       
    95 	}
       
    96 
       
    97 void BucketTotals::Total(Distribution::Data& aData)
       
    98 	{
       
    99 	int total = 0;
       
   100 	for (Distribution::Data::iterator p = aData.begin(), e = aData.end(); p != e; ++p)
       
   101 		{
       
   102 		const int* box = p->iBuckets;
       
   103 		int threadTotal = 0;
       
   104 		for (int j = p->iBucketsLength; --j >=0;)
       
   105 			{
       
   106 			threadTotal += box[j];
       
   107 			iTotals[j] += box[j];
       
   108 			}
       
   109 		p->iTotal = threadTotal;
       
   110 		total += threadTotal;
       
   111 		}
       
   112 	iTotal = total;
       
   113 	}
       
   114 
       
   115 void BucketTotals::Sort()
       
   116 	{
       
   117 	std::sort(iOrdering, iOrdering + iSize, Sorter(iTotals));
       
   118 	}
       
   119 
       
   120 inline int BucketTotals::Total() const
       
   121 	{return iTotal;}
       
   122 
       
   123 inline int BucketTotals::Map(int aBucket) const
       
   124 	{return iOrdering[aBucket];}
       
   125 
       
   126 inline int BucketTotals::operator[](int aBucket) const
       
   127 	{return iTotals[iOrdering[aBucket]];}
       
   128 
       
   129 inline Result BucketTotals::Sample(int aSample) const
       
   130 	{return Result(aSample, iTotal);}
       
   131 
       
   132 };
       
   133 
       
   134 inline Distribution::ThreadData::ThreadData(const Thread& aThread, int aSize)
       
   135 	:iThread(&aThread), iBuckets(BucketBox(aSize)), iTotal(0), iBucketsLength(aSize)
       
   136 	{}
       
   137 
       
   138 inline Distribution::ThreadData::ThreadData(int aCutoff)
       
   139 	:iTotal(aCutoff)
       
   140 	{}
       
   141 
       
   142 inline bool Distribution::ThreadData::operator<(const Distribution::ThreadData& aRhs) const
       
   143 	{return (iTotal > aRhs.iTotal);}
       
   144 
       
   145 Distribution::Distribution(CodeSpace& aCodeSpace, double aCutOff)
       
   146 	:iCodeSpace(aCodeSpace), iCutOff(aCutOff)
       
   147 	{
       
   148 	cout << "Profile distribution\n\n";
       
   149 	}
       
   150 
       
   151 void Distribution::Sample(unsigned , const Thread& aThread, PC aPc)
       
   152 //
       
   153 // Collect the sample in the bucket as allocated by the code space
       
   154 //
       
   155 	{
       
   156 	if (aThread.iIndex == iData.size())
       
   157 		iData.push_back(ThreadData(aThread,iCodeSpace.Size()));
       
   158 
       
   159 	///
       
   160 	int bucket = iCodeSpace.Bucket(aPc);
       
   161 	if (bucket >= iData[aThread.iIndex].iBucketsLength)
       
   162 		{
       
   163 		int* new_buckets = new int[bucket+1];
       
   164 		memset(new_buckets, 0, sizeof(int) * (bucket+1));
       
   165 		memcpy(new_buckets, iData[aThread.iIndex].iBuckets, sizeof(int) * iData[aThread.iIndex].iBucketsLength);
       
   166 		delete [] iData[aThread.iIndex].iBuckets;
       
   167 		iData[aThread.iIndex].iBuckets = new_buckets;
       
   168 		iData[aThread.iIndex].iBucketsLength = bucket+1;
       
   169 		}
       
   170 
       
   171 	++iData[aThread.iIndex].iBuckets[bucket];
       
   172 	}
       
   173 
       
   174 void Distribution::Complete(unsigned aTotal, unsigned aActive)
       
   175 	{
       
   176 	// accumulate thread and bucket totals
       
   177 	const int nbuckets = iCodeSpace.Size();
       
   178 	BucketTotals totals(iData, nbuckets);
       
   179 	if (iCodeSpace.Ordering() == CodeSpace::ERandom)
       
   180 		totals.Sort();
       
   181 
       
   182 	int cutoff = int(iCutOff * totals.Total() * 0.01);
       
   183 	std::sort(iData.begin(), iData.end());
       
   184 	iData.erase(std::upper_bound(iData.begin(), iData.end(), ThreadData(cutoff)), iData.end());
       
   185 //
       
   186 	cout.setf(ios::fixed, ios::floatfield);
       
   187 	cout.precision(2);
       
   188 //
       
   189 	cout << "Samples: " << aTotal << '\n';
       
   190 	cout << " Active: " << aActive << "  (" << double(aActive*100)/aTotal << "%)\n";
       
   191 	cout << "Counted: " << totals.Total() << "  (" << double(totals.Total()*100)/aTotal << "%)\n\n";
       
   192 	cout << setfill(' ');
       
   193 //
       
   194 	Data::iterator p, e;
       
   195 	if (!Analyse::Option(Analyse::ETotalOnly))
       
   196 		{
       
   197 		if (Analyse::Format() != Analyse::EExcel)
       
   198 			{
       
   199 			cout << "ID  Thread name\n";
       
   200 			char id = 'A';
       
   201 			for (p = iData.begin(), e = iData.end(); p != e; ++p)
       
   202 				cout << id++ << "   " << *p->iThread << '\n';
       
   203 			cout << '\n';
       
   204 
       
   205 			id = 'A';
       
   206 			for (p = iData.begin(), e = iData.end(); p != e; ++p)
       
   207 				cout << setw(4) << id++ << "    ";
       
   208 			cout << "  total\n\n";
       
   209 
       
   210 			for (p = iData.begin(), e = iData.end(); p != e; ++p)
       
   211 				cout << totals.Sample(p->iTotal) << " ";
       
   212 			cout << "  " << totals.Sample(totals.Total()) << "  total\n\n";
       
   213 			}
       
   214 		else
       
   215 			{
       
   216 			cout.precision(5);
       
   217 			for (p = iData.begin(), e = iData.end(); p != e; ++p)
       
   218 				cout << '\t' << *p->iThread;
       
   219 			cout << "\ttotal\n";
       
   220 			}
       
   221 		}
       
   222 
       
   223 	if (cutoff == 0 && iCodeSpace.Ordering() != CodeSpace::ELinear)
       
   224 		cutoff = 1;
       
   225 
       
   226 	for (int ix = 0; ix< nbuckets; ++ix)
       
   227 		{
       
   228 		int total = totals[ix];
       
   229 		if (total >= cutoff)
       
   230 			{
       
   231 			int jx = totals.Map(ix);
       
   232 			if (jx == CodeSpace::KOtherBucket && Analyse::Option(Analyse::ENoOther))
       
   233 				continue;
       
   234 			if (Analyse::Format() == Analyse::EExcel)
       
   235 				{
       
   236 				cout << iCodeSpace.Name(jx);
       
   237 				if (!Analyse::Option(Analyse::ETotalOnly))
       
   238 					{
       
   239 					for (p = iData.begin(), e = iData.end(); p != e; ++p)
       
   240 						cout << '\t' << totals.Sample(jx>=p->iBucketsLength ? 0 : p->iBuckets[jx]);
       
   241 					}
       
   242 				cout << '\t' << totals.Sample(total) << '\n';
       
   243 				}
       
   244 			else
       
   245 				{
       
   246 				if (!Analyse::Option(Analyse::ETotalOnly))
       
   247 					{
       
   248 					for (p = iData.begin(), e = iData.end(); p != e; ++p)
       
   249 						cout << totals.Sample(jx>=p->iBucketsLength ? 0 : p->iBuckets[jx]) << " ";
       
   250 					cout << "  ";
       
   251 					}
       
   252 				cout << totals.Sample(total) << "  " << iCodeSpace.Name(jx) << '\n';
       
   253 				}
       
   254 			}
       
   255 		}
       
   256 
       
   257 	if (!Analyse::Option(Analyse::ETotalOnly))
       
   258 		{
       
   259 		if (Analyse::Format() == Analyse::EExcel)
       
   260 			{
       
   261 			cout << "total";
       
   262 			for (p = iData.begin(), e = iData.end(); p != e; ++p)
       
   263 				cout << '\t' << totals.Sample(p->iTotal);
       
   264 			cout << '\t' << totals.Sample(totals.Total()) << '\n';
       
   265 			}
       
   266 		}
       
   267 	}