diff -r 000000000000 -r a41df078684a kerneltest/e32utils/analyse/distribution.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32utils/analyse/distribution.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -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 +#include +#else //!__MSVCDOTNET__ +#include +#include +#endif //__MSVCDOTNET__ + +#include + +// 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'; + } + } + }