--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32utils/analyse/distribution.cpp Thu Dec 17 09:24:54 2009 +0200
@@ -0,0 +1,267 @@
+// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+//
+
+#include "analyse.h"
+#include "distribution.h"
+#include "output.h"
+
+#ifdef __MSVCDOTNET__
+#include <ostream>
+#include <iomanip>
+#else //!__MSVCDOTNET__
+#include <ostream.h>
+#include <iomanip.h>
+#endif //__MSVCDOTNET__
+
+#include <algorithm>
+
+// class Distribution
+
+namespace {
+
+int* BucketBox(int aSize)
+ {
+ int* buckets = new int[aSize];
+ memset(buckets, 0, sizeof(int) * aSize);
+ return buckets;
+ }
+
+class BucketTotals
+ {
+private:
+ class Generator
+ {
+ public:
+ inline Generator()
+ :iValue(0)
+ {}
+ inline int operator()()
+ {return iValue++;}
+ private:
+ int iValue;
+ };
+ class Sorter
+ {
+ public:
+ inline Sorter(const int* aTotals)
+ :iTotals(aTotals)
+ {}
+ inline bool operator()(int aLhs, int aRhs) const
+ {return (iTotals[aLhs] > iTotals[aRhs]);}
+ private:
+ const int* iTotals;
+ };
+public:
+ BucketTotals(Distribution::Data& aData, int aSize);
+ ~BucketTotals();
+ void Sort();
+//
+ inline int Total() const;
+ inline int Map(int aBucket) const;
+ inline int operator[](int aBucket) const;
+ inline Result Sample(int aSample) const;
+private:
+ void Total(Distribution::Data& aData);
+private:
+ int iSize;
+ int* iTotals;
+ int* iOrdering;
+ int iTotal;
+ };
+
+BucketTotals::BucketTotals(Distribution::Data& aData, int aSize)
+ :iSize(aSize), iTotals(BucketBox(aSize)), iOrdering(BucketBox(aSize))
+ {
+ Total(aData);
+ std::generate_n(iOrdering, iSize, Generator());
+ }
+
+BucketTotals::~BucketTotals()
+ {
+ delete [] iTotals;
+ delete [] iOrdering;
+ }
+
+void BucketTotals::Total(Distribution::Data& aData)
+ {
+ int total = 0;
+ for (Distribution::Data::iterator p = aData.begin(), e = aData.end(); p != e; ++p)
+ {
+ const int* box = p->iBuckets;
+ int threadTotal = 0;
+ for (int j = p->iBucketsLength; --j >=0;)
+ {
+ threadTotal += box[j];
+ iTotals[j] += box[j];
+ }
+ p->iTotal = threadTotal;
+ total += threadTotal;
+ }
+ iTotal = total;
+ }
+
+void BucketTotals::Sort()
+ {
+ std::sort(iOrdering, iOrdering + iSize, Sorter(iTotals));
+ }
+
+inline int BucketTotals::Total() const
+ {return iTotal;}
+
+inline int BucketTotals::Map(int aBucket) const
+ {return iOrdering[aBucket];}
+
+inline int BucketTotals::operator[](int aBucket) const
+ {return iTotals[iOrdering[aBucket]];}
+
+inline Result BucketTotals::Sample(int aSample) const
+ {return Result(aSample, iTotal);}
+
+};
+
+inline Distribution::ThreadData::ThreadData(const Thread& aThread, int aSize)
+ :iThread(&aThread), iBuckets(BucketBox(aSize)), iTotal(0), iBucketsLength(aSize)
+ {}
+
+inline Distribution::ThreadData::ThreadData(int aCutoff)
+ :iTotal(aCutoff)
+ {}
+
+inline bool Distribution::ThreadData::operator<(const Distribution::ThreadData& aRhs) const
+ {return (iTotal > aRhs.iTotal);}
+
+Distribution::Distribution(CodeSpace& aCodeSpace, double aCutOff)
+ :iCodeSpace(aCodeSpace), iCutOff(aCutOff)
+ {
+ cout << "Profile distribution\n\n";
+ }
+
+void Distribution::Sample(unsigned , const Thread& aThread, PC aPc)
+//
+// Collect the sample in the bucket as allocated by the code space
+//
+ {
+ if (aThread.iIndex == iData.size())
+ iData.push_back(ThreadData(aThread,iCodeSpace.Size()));
+
+ ///
+ int bucket = iCodeSpace.Bucket(aPc);
+ if (bucket >= iData[aThread.iIndex].iBucketsLength)
+ {
+ int* new_buckets = new int[bucket+1];
+ memset(new_buckets, 0, sizeof(int) * (bucket+1));
+ memcpy(new_buckets, iData[aThread.iIndex].iBuckets, sizeof(int) * iData[aThread.iIndex].iBucketsLength);
+ delete [] iData[aThread.iIndex].iBuckets;
+ iData[aThread.iIndex].iBuckets = new_buckets;
+ iData[aThread.iIndex].iBucketsLength = bucket+1;
+ }
+
+ ++iData[aThread.iIndex].iBuckets[bucket];
+ }
+
+void Distribution::Complete(unsigned aTotal, unsigned aActive)
+ {
+ // accumulate thread and bucket totals
+ const int nbuckets = iCodeSpace.Size();
+ BucketTotals totals(iData, nbuckets);
+ if (iCodeSpace.Ordering() == CodeSpace::ERandom)
+ totals.Sort();
+
+ int cutoff = int(iCutOff * totals.Total() * 0.01);
+ std::sort(iData.begin(), iData.end());
+ iData.erase(std::upper_bound(iData.begin(), iData.end(), ThreadData(cutoff)), iData.end());
+//
+ cout.setf(ios::fixed, ios::floatfield);
+ cout.precision(2);
+//
+ cout << "Samples: " << aTotal << '\n';
+ cout << " Active: " << aActive << " (" << double(aActive*100)/aTotal << "%)\n";
+ cout << "Counted: " << totals.Total() << " (" << double(totals.Total()*100)/aTotal << "%)\n\n";
+ cout << setfill(' ');
+//
+ Data::iterator p, e;
+ if (!Analyse::Option(Analyse::ETotalOnly))
+ {
+ if (Analyse::Format() != Analyse::EExcel)
+ {
+ cout << "ID Thread name\n";
+ char id = 'A';
+ for (p = iData.begin(), e = iData.end(); p != e; ++p)
+ cout << id++ << " " << *p->iThread << '\n';
+ cout << '\n';
+
+ id = 'A';
+ for (p = iData.begin(), e = iData.end(); p != e; ++p)
+ cout << setw(4) << id++ << " ";
+ cout << " total\n\n";
+
+ for (p = iData.begin(), e = iData.end(); p != e; ++p)
+ cout << totals.Sample(p->iTotal) << " ";
+ cout << " " << totals.Sample(totals.Total()) << " total\n\n";
+ }
+ else
+ {
+ cout.precision(5);
+ for (p = iData.begin(), e = iData.end(); p != e; ++p)
+ cout << '\t' << *p->iThread;
+ cout << "\ttotal\n";
+ }
+ }
+
+ if (cutoff == 0 && iCodeSpace.Ordering() != CodeSpace::ELinear)
+ cutoff = 1;
+
+ for (int ix = 0; ix< nbuckets; ++ix)
+ {
+ int total = totals[ix];
+ if (total >= cutoff)
+ {
+ int jx = totals.Map(ix);
+ if (jx == CodeSpace::KOtherBucket && Analyse::Option(Analyse::ENoOther))
+ continue;
+ if (Analyse::Format() == Analyse::EExcel)
+ {
+ cout << iCodeSpace.Name(jx);
+ if (!Analyse::Option(Analyse::ETotalOnly))
+ {
+ for (p = iData.begin(), e = iData.end(); p != e; ++p)
+ cout << '\t' << totals.Sample(jx>=p->iBucketsLength ? 0 : p->iBuckets[jx]);
+ }
+ cout << '\t' << totals.Sample(total) << '\n';
+ }
+ else
+ {
+ if (!Analyse::Option(Analyse::ETotalOnly))
+ {
+ for (p = iData.begin(), e = iData.end(); p != e; ++p)
+ cout << totals.Sample(jx>=p->iBucketsLength ? 0 : p->iBuckets[jx]) << " ";
+ cout << " ";
+ }
+ cout << totals.Sample(total) << " " << iCodeSpace.Name(jx) << '\n';
+ }
+ }
+ }
+
+ if (!Analyse::Option(Analyse::ETotalOnly))
+ {
+ if (Analyse::Format() == Analyse::EExcel)
+ {
+ cout << "total";
+ for (p = iData.begin(), e = iData.end(); p != e; ++p)
+ cout << '\t' << totals.Sample(p->iTotal);
+ cout << '\t' << totals.Sample(totals.Total()) << '\n';
+ }
+ }
+ }