os/kernelhwsrv/kerneltest/e32utils/analyse/distribution.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 	}