Some refactoring:

* Added new class ProfiledEntity which Thread derives from and which is the
  new dependency for the profile result classes (instead of Thread).
* Renamed *ThreadProfileResult to *ProfileResult and *ThreadImage to
  *ProfileResultImage and move ProfileResult[Image] into a new header/source
  file.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35546 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2010-02-20 20:31:04 +00:00
parent 8b64284b67
commit 5fc675d57e
13 changed files with 526 additions and 436 deletions
@@ -1,9 +1,10 @@
/* /*
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include "BasicThreadProfileResult.h"
#include "BasicProfileResult.h"
#include <stdio.h> #include <stdio.h>
@@ -11,6 +12,7 @@
#include <new> #include <new>
#include "Options.h" #include "Options.h"
#include "ProfiledEntity.h"
struct HitSymbol { struct HitSymbol {
@@ -25,25 +27,25 @@ struct HitSymbol {
}; };
// #pragma mark - BasicThreadImage // #pragma mark - BasicProfileResultImage
BasicThreadImage::BasicThreadImage(Image* image) BasicProfileResultImage::BasicProfileResultImage(Image* image)
: :
ThreadImage(image), ProfileResultImage(image),
fSymbolHits(NULL), fSymbolHits(NULL),
fUnknownHits(0) fUnknownHits(0)
{ {
} }
BasicThreadImage::~BasicThreadImage() BasicProfileResultImage::~BasicProfileResultImage()
{ {
} }
status_t status_t
BasicThreadImage::Init() BasicProfileResultImage::Init()
{ {
int32 symbolCount = fImage->SymbolCount(); int32 symbolCount = fImage->SymbolCount();
fSymbolHits = new(std::nothrow) int64[symbolCount]; fSymbolHits = new(std::nothrow) int64[symbolCount];
@@ -57,7 +59,7 @@ BasicThreadImage::Init()
bool bool
BasicThreadImage::AddHit(addr_t address) BasicProfileResultImage::AddHit(addr_t address)
{ {
int32 symbolIndex = fImage->FindSymbol(address); int32 symbolIndex = fImage->FindSymbol(address);
if (symbolIndex < 0) if (symbolIndex < 0)
@@ -71,7 +73,7 @@ BasicThreadImage::AddHit(addr_t address)
void void
BasicThreadImage::AddUnknownHit() BasicProfileResultImage::AddUnknownHit()
{ {
fUnknownHits++; fUnknownHits++;
fTotalHits++; fTotalHits++;
@@ -79,37 +81,37 @@ BasicThreadImage::AddUnknownHit()
void void
BasicThreadImage::AddSymbolHit(int32 symbolIndex) BasicProfileResultImage::AddSymbolHit(int32 symbolIndex)
{ {
fSymbolHits[symbolIndex]++; fSymbolHits[symbolIndex]++;
} }
void void
BasicThreadImage::AddImageHit() BasicProfileResultImage::AddImageHit()
{ {
fTotalHits++; fTotalHits++;
} }
const int64* const int64*
BasicThreadImage::SymbolHits() const BasicProfileResultImage::SymbolHits() const
{ {
return fSymbolHits; return fSymbolHits;
} }
int64 int64
BasicThreadImage::UnknownHits() const BasicProfileResultImage::UnknownHits() const
{ {
return fUnknownHits; return fUnknownHits;
} }
// #pragma mark - BasicThreadProfileResult // #pragma mark - BasicProfileResult
BasicThreadProfileResult::BasicThreadProfileResult() BasicProfileResult::BasicProfileResult()
: :
fTotalTicks(0), fTotalTicks(0),
fUnkownTicks(0), fUnkownTicks(0),
@@ -120,23 +122,23 @@ BasicThreadProfileResult::BasicThreadProfileResult()
void void
BasicThreadProfileResult::AddDroppedTicks(int32 dropped) BasicProfileResult::AddDroppedTicks(int32 dropped)
{ {
fDroppedTicks += dropped; fDroppedTicks += dropped;
} }
void void
BasicThreadProfileResult::PrintResults() BasicProfileResult::PrintResults()
{ {
// get hit images // get hit images
BasicThreadImage* images[fOldImages.Count() + fImages.Count()]; BasicProfileResultImage* images[fOldImages.Count() + fImages.Count()];
int32 imageCount = GetHitImages(images); int32 imageCount = GetHitImages(images);
// count symbols // count symbols
int32 symbolCount = 0; int32 symbolCount = 0;
for (int32 k = 0; k < imageCount; k++) { for (int32 k = 0; k < imageCount; k++) {
BasicThreadImage* image = images[k]; BasicProfileResultImage* image = images[k];
if (image->TotalHits() > image->UnknownHits()) if (image->TotalHits() > image->UnknownHits())
symbolCount += image->GetImage()->SymbolCount(); symbolCount += image->GetImage()->SymbolCount();
} }
@@ -146,7 +148,7 @@ BasicThreadProfileResult::PrintResults()
int32 hitSymbolCount = 0; int32 hitSymbolCount = 0;
for (int32 k = 0; k < imageCount; k++) { for (int32 k = 0; k < imageCount; k++) {
BasicThreadImage* image = images[k]; BasicProfileResultImage* image = images[k];
if (image->TotalHits() > image->UnknownHits()) { if (image->TotalHits() > image->UnknownHits()) {
Symbol** symbols = image->GetImage()->Symbols(); Symbol** symbols = image->GetImage()->Symbols();
const int64* symbolHits = image->SymbolHits(); const int64* symbolHits = image->SymbolHits();
@@ -166,8 +168,9 @@ BasicThreadProfileResult::PrintResults()
std::sort(hitSymbols, hitSymbols + hitSymbolCount); std::sort(hitSymbols, hitSymbols + hitSymbolCount);
int64 totalTicks = fTotalTicks; int64 totalTicks = fTotalTicks;
fprintf(gOptions.output, "\nprofiling results for thread \"%s\" " fprintf(gOptions.output, "\nprofiling results for %s \"%s\" "
"(%ld):\n", fThread->Name(), fThread->ID()); "(%" B_PRId32 "):\n", fEntity->EntityType(), fEntity->EntityName(),
fEntity->EntityID());
fprintf(gOptions.output, " tick interval: %lld us\n", fInterval); fprintf(gOptions.output, " tick interval: %lld us\n", fInterval);
fprintf(gOptions.output, " total ticks: %lld (%lld us)\n", fprintf(gOptions.output, " total ticks: %lld (%lld us)\n",
totalTicks, totalTicks * fInterval); totalTicks, totalTicks * fInterval);
@@ -190,7 +193,7 @@ BasicThreadProfileResult::PrintResults()
fprintf(gOptions.output, " ---------------------------------------" fprintf(gOptions.output, " ---------------------------------------"
"---------------------------------------\n"); "---------------------------------------\n");
for (int32 k = 0; k < imageCount; k++) { for (int32 k = 0; k < imageCount; k++) {
BasicThreadImage* image = images[k]; BasicProfileResultImage* image = images[k];
fprintf(gOptions.output, " %10lld %10lld %7ld %s\n", fprintf(gOptions.output, " %10lld %10lld %7ld %s\n",
image->TotalHits(), image->UnknownHits(), image->TotalHits(), image->UnknownHits(),
image->GetImage()->ID(), image->GetImage()->Name()); image->GetImage()->ID(), image->GetImage()->Name());
@@ -216,18 +219,18 @@ BasicThreadProfileResult::PrintResults()
} }
BasicThreadImage* BasicProfileResultImage*
BasicThreadProfileResult::CreateThreadImage(Image* image) BasicProfileResult::CreateProfileResultImage(Image* image)
{ {
return new(std::nothrow) BasicThreadImage(image); return new(std::nothrow) BasicProfileResultImage(image);
} }
// #pragma mark - InclusiveThreadProfileResult // #pragma mark - InclusiveProfileResult
void void
InclusiveThreadProfileResult::AddSamples(addr_t* samples, int32 sampleCount) InclusiveProfileResult::AddSamples(addr_t* samples, int32 sampleCount)
{ {
// Sort the samples. This way hits of the same symbol are // Sort the samples. This way hits of the same symbol are
// successive and we can avoid incrementing the hit count of the // successive and we can avoid incrementing the hit count of the
@@ -235,12 +238,12 @@ InclusiveThreadProfileResult::AddSamples(addr_t* samples, int32 sampleCount)
std::sort(samples, samples + sampleCount); std::sort(samples, samples + sampleCount);
int32 unknownSamples = 0; int32 unknownSamples = 0;
BasicThreadImage* previousImage = NULL; BasicProfileResultImage* previousImage = NULL;
int32 previousSymbol = -1; int32 previousSymbol = -1;
for (int32 i = 0; i < sampleCount; i++) { for (int32 i = 0; i < sampleCount; i++) {
addr_t address = samples[i]; addr_t address = samples[i];
BasicThreadImage* image = FindImage(address); BasicProfileResultImage* image = FindImage(address);
int32 symbol = -1; int32 symbol = -1;
if (image != NULL) { if (image != NULL) {
symbol = image->GetImage()->FindSymbol(address); symbol = image->GetImage()->FindSymbol(address);
@@ -266,15 +269,15 @@ InclusiveThreadProfileResult::AddSamples(addr_t* samples, int32 sampleCount)
} }
// #pragma mark - ExclusiveThreadProfileResult // #pragma mark - ExclusiveProfileResult
void void
ExclusiveThreadProfileResult::AddSamples(addr_t* samples, int32 sampleCount) ExclusiveProfileResult::AddSamples(addr_t* samples, int32 sampleCount)
{ {
BasicThreadImage* image = NULL; BasicProfileResultImage* image = NULL;
// the image in which we hit a symbol // the image in which we hit a symbol
BasicThreadImage* firstImage = NULL; BasicProfileResultImage* firstImage = NULL;
// the first image we hit, != image if no symbol was hit // the first image we hit, != image if no symbol was hit
for (int32 k = 0; k < sampleCount; k++) { for (int32 k = 0; k < sampleCount; k++) {
@@ -1,18 +1,19 @@
/* /*
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef BASIC_THREAD_PROFILE_RESULT_H #ifndef BASIC_PROFILE_RESULT_H
#define BASIC_THREAD_PROFILE_RESULT_H #define BASIC_PROFILE_RESULT_H
#include "Thread.h"
class BasicThreadImage : public ThreadImage, #include "ProfileResult.h"
public DoublyLinkedListLinkImpl<BasicThreadImage> {
class BasicProfileResultImage : public ProfileResultImage,
public DoublyLinkedListLinkImpl<BasicProfileResultImage> {
public: public:
BasicThreadImage(Image* image); BasicProfileResultImage(Image* image);
virtual ~BasicThreadImage(); virtual ~BasicProfileResultImage();
virtual status_t Init(); virtual status_t Init();
@@ -30,15 +31,15 @@ private:
}; };
class BasicThreadProfileResult class BasicProfileResult
: public AbstractThreadProfileResult<BasicThreadImage> { : public AbstractProfileResult<BasicProfileResultImage> {
public: public:
BasicThreadProfileResult(); BasicProfileResult();
virtual void AddDroppedTicks(int32 dropped); virtual void AddDroppedTicks(int32 dropped);
virtual void PrintResults(); virtual void PrintResults();
virtual BasicThreadImage* CreateThreadImage(Image* image); virtual BasicProfileResultImage* CreateProfileResultImage(Image* image);
protected: protected:
int64 fTotalTicks; int64 fTotalTicks;
@@ -48,18 +49,18 @@ protected:
}; };
class InclusiveThreadProfileResult : public BasicThreadProfileResult { class InclusiveProfileResult : public BasicProfileResult {
public: public:
virtual void AddSamples(addr_t* samples, virtual void AddSamples(addr_t* samples,
int32 sampleCount); int32 sampleCount);
}; };
class ExclusiveThreadProfileResult : public BasicThreadProfileResult { class ExclusiveProfileResult : public BasicProfileResult {
public: public:
virtual void AddSamples(addr_t* samples, virtual void AddSamples(addr_t* samples,
int32 sampleCount); int32 sampleCount);
}; };
#endif // BASIC_THREAD_PROFILE_RESULT_H #endif // BASIC_PROFILE_RESULT_H
@@ -1,9 +1,10 @@
/* /*
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include "CallgrindThreadProfileResult.h"
#include "CallgrindProfileResult.h"
#include <errno.h> #include <errno.h>
#include <sys/stat.h> #include <sys/stat.h>
@@ -12,21 +13,22 @@
#include <new> #include <new>
#include "Options.h" #include "Options.h"
#include "ProfiledEntity.h"
// #pragma mark - CallgrindThreadImage // #pragma mark - CallgrindProfileResultImage
CallgrindThreadImage::CallgrindThreadImage(Image* image) CallgrindProfileResultImage::CallgrindProfileResultImage(Image* image)
: :
ThreadImage(image), ProfileResultImage(image),
fFunctions(NULL), fFunctions(NULL),
fOutputIndex(0) fOutputIndex(0)
{ {
} }
CallgrindThreadImage::~CallgrindThreadImage() CallgrindProfileResultImage::~CallgrindProfileResultImage()
{ {
int32 symbolCount = fImage->SymbolCount(); int32 symbolCount = fImage->SymbolCount();
for (int32 i = 0; i < symbolCount; i++) { for (int32 i = 0; i < symbolCount; i++) {
@@ -42,7 +44,7 @@ CallgrindThreadImage::~CallgrindThreadImage()
status_t status_t
CallgrindThreadImage::Init() CallgrindProfileResultImage::Init()
{ {
int32 symbolCount = fImage->SymbolCount(); int32 symbolCount = fImage->SymbolCount();
fFunctions = new(std::nothrow) CallgrindFunction[symbolCount]; fFunctions = new(std::nothrow) CallgrindFunction[symbolCount];
@@ -56,8 +58,8 @@ CallgrindThreadImage::Init()
void void
CallgrindThreadImage::AddSymbolHit(int32 symbolIndex, CallgrindProfileResultImage::AddSymbolHit(int32 symbolIndex,
CallgrindThreadImage* calledImage, int32 calledSymbol) CallgrindProfileResultImage* calledImage, int32 calledSymbol)
{ {
fTotalHits++; fTotalHits++;
@@ -92,30 +94,30 @@ CallgrindThreadImage::AddSymbolHit(int32 symbolIndex,
CallgrindFunction* CallgrindFunction*
CallgrindThreadImage::Functions() const CallgrindProfileResultImage::Functions() const
{ {
return fFunctions; return fFunctions;
} }
int32 int32
CallgrindThreadImage::OutputIndex() const CallgrindProfileResultImage::OutputIndex() const
{ {
return fOutputIndex; return fOutputIndex;
} }
void void
CallgrindThreadImage::SetOutputIndex(int32 index) CallgrindProfileResultImage::SetOutputIndex(int32 index)
{ {
fOutputIndex = index; fOutputIndex = index;
} }
// #pragma mark - CallgrindThreadProfileResult // #pragma mark - CallgrindProfileResult
CallgrindThreadProfileResult::CallgrindThreadProfileResult() CallgrindProfileResult::CallgrindProfileResult()
: :
fTotalTicks(0), fTotalTicks(0),
fUnkownTicks(0), fUnkownTicks(0),
@@ -127,16 +129,16 @@ CallgrindThreadProfileResult::CallgrindThreadProfileResult()
void void
CallgrindThreadProfileResult::AddSamples(addr_t* samples, int32 sampleCount) CallgrindProfileResult::AddSamples(addr_t* samples, int32 sampleCount)
{ {
int32 unknownSamples = 0; int32 unknownSamples = 0;
CallgrindThreadImage* previousImage = NULL; CallgrindProfileResultImage* previousImage = NULL;
int32 previousSymbol = -1; int32 previousSymbol = -1;
// TODO: That probably doesn't work with recursive functions. // TODO: That probably doesn't work with recursive functions.
for (int32 i = 0; i < sampleCount; i++) { for (int32 i = 0; i < sampleCount; i++) {
addr_t address = samples[i]; addr_t address = samples[i];
CallgrindThreadImage* image = FindImage(address); CallgrindProfileResultImage* image = FindImage(address);
int32 symbol = -1; int32 symbol = -1;
if (image != NULL) { if (image != NULL) {
symbol = image->GetImage()->FindSymbol(address); symbol = image->GetImage()->FindSymbol(address);
@@ -157,31 +159,31 @@ CallgrindThreadProfileResult::AddSamples(addr_t* samples, int32 sampleCount)
void void
CallgrindThreadProfileResult::AddDroppedTicks(int32 dropped) CallgrindProfileResult::AddDroppedTicks(int32 dropped)
{ {
fDroppedTicks += dropped; fDroppedTicks += dropped;
} }
void void
CallgrindThreadProfileResult::PrintResults() CallgrindProfileResult::PrintResults()
{ {
// create output file // create output file
// create output dir // create output dir
mkdir(gOptions.callgrind_directory, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); mkdir(gOptions.callgrind_directory, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
// get the thread name and replace slashes by hyphens // get the entity name and replace slashes by hyphens
char threadName[B_OS_NAME_LENGTH]; char entityName[B_OS_NAME_LENGTH];
strlcpy(threadName, fThread->Name(), sizeof(threadName)); strlcpy(entityName, fEntity->EntityName(), sizeof(entityName));
char* slash = threadName; char* slash = entityName;
while ((slash = strchr(slash, '/')) != NULL) while ((slash = strchr(slash, '/')) != NULL)
*slash = '-'; *slash = '-';
// create the file name // create the file name
char fileName[B_PATH_NAME_LENGTH]; char fileName[B_PATH_NAME_LENGTH];
snprintf(fileName, sizeof(fileName), "%s/callgrind.out.%ld.%s.%lldms", snprintf(fileName, sizeof(fileName), "%s/callgrind.out.%ld.%s.%lldms",
gOptions.callgrind_directory, fThread->ID(), threadName, gOptions.callgrind_directory, fEntity->EntityID(), entityName,
fTotalTicks * fInterval); fTotalTicks * fInterval);
// create the file // create the file
@@ -195,8 +197,8 @@ CallgrindThreadProfileResult::PrintResults()
// write the header // write the header
fprintf(out, "version: 1\n"); fprintf(out, "version: 1\n");
fprintf(out, "creator: Haiku profile\n"); fprintf(out, "creator: Haiku profile\n");
fprintf(out, "pid: %ld\n", fThread->ID()); fprintf(out, "pid: %ld\n", fEntity->EntityID());
fprintf(out, "cmd: %s\n", fThread->Name()); fprintf(out, "cmd: %s\n", fEntity->EntityName());
fprintf(out, "part: 1\n\n"); fprintf(out, "part: 1\n\n");
fprintf(out, "positions: line\n"); fprintf(out, "positions: line\n");
@@ -204,11 +206,11 @@ CallgrindThreadProfileResult::PrintResults()
fprintf(out, "summary: %lld %lld\n", fTotalTicks, fTotalTicks * fInterval); fprintf(out, "summary: %lld %lld\n", fTotalTicks, fTotalTicks * fInterval);
// get hit images // get hit images
CallgrindThreadImage* images[fOldImages.Count() + fImages.Count()]; CallgrindProfileResultImage* images[fOldImages.Count() + fImages.Count()];
int32 imageCount = GetHitImages(images); int32 imageCount = GetHitImages(images);
for (int32 i = 0; i < imageCount; i++) { for (int32 i = 0; i < imageCount; i++) {
CallgrindThreadImage* image = images[i]; CallgrindProfileResultImage* image = images[i];
CallgrindFunction* functions = image->Functions(); CallgrindFunction* functions = image->Functions();
int32 imageSymbolCount = image->GetImage()->SymbolCount(); int32 imageSymbolCount = image->GetImage()->SymbolCount();
@@ -255,16 +257,16 @@ CallgrindThreadProfileResult::PrintResults()
} }
CallgrindThreadImage* CallgrindProfileResultImage*
CallgrindThreadProfileResult::CreateThreadImage(Image* image) CallgrindProfileResult::CreateProfileResultImage(Image* image)
{ {
return new(std::nothrow) CallgrindThreadImage(image); return new(std::nothrow) CallgrindProfileResultImage(image);
} }
void void
CallgrindThreadProfileResult::_PrintFunction(FILE* out, CallgrindProfileResult::_PrintFunction(FILE* out,
CallgrindThreadImage* image, int32 functionIndex, bool called) CallgrindProfileResultImage* image, int32 functionIndex, bool called)
{ {
if (image->OutputIndex() == 0) { if (image->OutputIndex() == 0) {
// need to print the image name // need to print the image name
@@ -1,25 +1,26 @@
/* /*
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef CALLGRIND_THREAD_PROFILE_RESULT_H #ifndef CALLGRIND_PROFILE_RESULT_H
#define CALLGRIND_THREAD_PROFILE_RESULT_H #define CALLGRIND_PROFILE_RESULT_H
#include <stdio.h> #include <stdio.h>
#include "Thread.h" #include "ProfileResult.h"
class CallgrindThreadImage; class CallgrindProfileResultImage;
struct CallgrindCalledFunction { struct CallgrindCalledFunction {
CallgrindCalledFunction* next; CallgrindCalledFunction* next;
CallgrindThreadImage* image; CallgrindProfileResultImage* image;
int32 function; int32 function;
int64 hits; int64 hits;
CallgrindCalledFunction(CallgrindThreadImage* image, int32 function) CallgrindCalledFunction(CallgrindProfileResultImage* image, int32 function)
: :
next(NULL), next(NULL),
image(image), image(image),
@@ -38,16 +39,16 @@ struct CallgrindFunction {
}; };
class CallgrindThreadImage : public ThreadImage, class CallgrindProfileResultImage : public ProfileResultImage,
public DoublyLinkedListLinkImpl<CallgrindThreadImage> { public DoublyLinkedListLinkImpl<CallgrindProfileResultImage> {
public: public:
CallgrindThreadImage(Image* image); CallgrindProfileResultImage(Image* image);
virtual ~CallgrindThreadImage(); virtual ~CallgrindProfileResultImage();
virtual status_t Init(); virtual status_t Init();
inline void AddSymbolHit(int32 symbolIndex, inline void AddSymbolHit(int32 symbolIndex,
CallgrindThreadImage* calledImage, CallgrindProfileResultImage* calledImage,
int32 calledSymbol); int32 calledSymbol);
inline CallgrindFunction* Functions() const; inline CallgrindFunction* Functions() const;
@@ -61,21 +62,21 @@ private:
}; };
class CallgrindThreadProfileResult class CallgrindProfileResult
: public AbstractThreadProfileResult<CallgrindThreadImage> { : public AbstractProfileResult<CallgrindProfileResultImage> {
public: public:
CallgrindThreadProfileResult(); CallgrindProfileResult();
virtual void AddSamples(addr_t* samples, virtual void AddSamples(addr_t* samples,
int32 sampleCount); int32 sampleCount);
virtual void AddDroppedTicks(int32 dropped); virtual void AddDroppedTicks(int32 dropped);
virtual void PrintResults(); virtual void PrintResults();
virtual CallgrindThreadImage* CreateThreadImage(Image* image); virtual CallgrindProfileResultImage* CreateProfileResultImage(Image* image);
private: private:
void _PrintFunction(FILE* out, void _PrintFunction(FILE* out,
CallgrindThreadImage* image, CallgrindProfileResultImage* image,
int32 functionIndex, bool called); int32 functionIndex, bool called);
private: private:
int64 fTotalTicks; int64 fTotalTicks;
@@ -86,4 +87,4 @@ private:
}; };
#endif // CALLGRIND_THREAD_PROFILE_RESULT_H #endif // CALLGRIND_PROFILE_RESULT_H
+4 -2
View File
@@ -10,9 +10,11 @@ SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ;
BinCommand profile BinCommand profile
: :
BasicThreadProfileResult.cpp BasicProfileResult.cpp
CallgrindThreadProfileResult.cpp CallgrindProfileResult.cpp
Image.cpp Image.cpp
ProfiledEntity.cpp
ProfileResult.cpp
SharedImage.cpp SharedImage.cpp
Team.cpp Team.cpp
Thread.cpp Thread.cpp
+63
View File
@@ -0,0 +1,63 @@
/*
* Copyright 2008-2010, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "ProfileResult.h"
// #pragma mark - ProfileResultImage
ProfileResultImage::ProfileResultImage(Image* image)
:
fImage(image),
fTotalHits(0)
{
fImage->AddReference();
}
ProfileResultImage::~ProfileResultImage()
{
fImage->RemoveReference();
}
status_t
ProfileResultImage::Init()
{
return B_OK;
}
// #pragma mark - ProfileResult
ProfileResult::ProfileResult()
:
fEntity(NULL),
fInterval(1)
{
}
ProfileResult::~ProfileResult()
{
}
status_t
ProfileResult::Init(ProfiledEntity* entity)
{
fEntity = entity;
return B_OK;
}
void
ProfileResult::SetInterval(bigtime_t interval)
{
fInterval = interval;
}
+265
View File
@@ -0,0 +1,265 @@
/*
* Copyright 2008-2010, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef PROFILE_RESULT_H
#define PROFILE_RESULT_H
#include <util/DoublyLinkedList.h>
#include "Image.h"
class ProfiledEntity;
class Team;
class ProfileResultImage {
public:
ProfileResultImage(Image* image);
virtual ~ProfileResultImage();
virtual status_t Init();
inline image_id ID() const;
inline Image* GetImage() const;
inline bool ContainsAddress(addr_t address) const;
inline int64 TotalHits() const;
protected:
Image* fImage;
int64 fTotalHits;
};
class ProfileResult {
public:
ProfileResult();
virtual ~ProfileResult();
virtual status_t Init(ProfiledEntity* entity);
void SetInterval(bigtime_t interval);
virtual void SetLazyImages(bool lazy) = 0;
virtual status_t AddImage(Image* image) = 0;
virtual void RemoveImage(Image* image) = 0;
virtual void SynchronizeImages(int32 event) = 0;
virtual void AddSamples(addr_t* samples,
int32 sampleCount) = 0;
virtual void AddDroppedTicks(int32 dropped) = 0;
virtual void PrintResults() = 0;
protected:
ProfiledEntity* fEntity;
bigtime_t fInterval;
};
template<typename ProfileResultImageType>
class AbstractProfileResult : public ProfileResult {
public:
AbstractProfileResult();
virtual ~AbstractProfileResult();
virtual void SetLazyImages(bool lazy);
virtual status_t AddImage(Image* image);
virtual void RemoveImage(Image* image);
virtual void SynchronizeImages(int32 event);
ProfileResultImageType* FindImage(addr_t address) const;
int32 GetHitImages(
ProfileResultImageType** images) const;
virtual ProfileResultImageType* CreateProfileResultImage(Image* image) = 0;
protected:
typedef DoublyLinkedList<ProfileResultImageType> ImageList;
ImageList fImages;
ImageList fNewImages;
ImageList fOldImages;
bool fLazyImages;
};
// #pragma mark -
image_id
ProfileResultImage::ID() const
{
return fImage->ID();
}
bool
ProfileResultImage::ContainsAddress(addr_t address) const
{
return fImage->ContainsAddress(address);
}
Image*
ProfileResultImage::GetImage() const
{
return fImage;
}
int64
ProfileResultImage::TotalHits() const
{
return fTotalHits;
}
// #pragma mark - AbstractProfileResult
template<typename ProfileResultImageType>
AbstractProfileResult<ProfileResultImageType>::AbstractProfileResult()
:
fImages(),
fNewImages(),
fOldImages(),
fLazyImages(true)
{
}
template<typename ProfileResultImageType>
AbstractProfileResult<ProfileResultImageType>::~AbstractProfileResult()
{
while (ProfileResultImageType* image = fImages.RemoveHead())
delete image;
while (ProfileResultImageType* image = fOldImages.RemoveHead())
delete image;
}
template<typename ProfileResultImageType>
void
AbstractProfileResult<ProfileResultImageType>::SetLazyImages(bool lazy)
{
fLazyImages = lazy;
}
template<typename ProfileResultImageType>
status_t
AbstractProfileResult<ProfileResultImageType>::AddImage(Image* image)
{
ProfileResultImageType* resultImage = CreateProfileResultImage(image);
if (resultImage == NULL)
return B_NO_MEMORY;
status_t error = resultImage->Init();
if (error != B_OK) {
delete resultImage;
return error;
}
if (fLazyImages)
fNewImages.Add(resultImage);
else
fImages.Add(resultImage);
return B_OK;
}
template<typename ProfileResultImageType>
void
AbstractProfileResult<ProfileResultImageType>::RemoveImage(Image* image)
{
typename ImageList::Iterator it = fImages.GetIterator();
while (ProfileResultImageType* resultImage = it.Next()) {
if (resultImage->GetImage() == image) {
it.Remove();
if (resultImage->TotalHits() > 0)
fOldImages.Add(resultImage);
else
delete resultImage;
break;
}
}
}
template<typename ProfileResultImageType>
void
AbstractProfileResult<ProfileResultImageType>::SynchronizeImages(int32 event)
{
// remove obsolete images
typename ImageList::Iterator it = fImages.GetIterator();
while (ProfileResultImageType* image = it.Next()) {
int32 deleted = image->GetImage()->DeletionEvent();
if (deleted >= 0 && event >= deleted) {
it.Remove();
if (image->TotalHits() > 0)
fOldImages.Add(image);
else
delete image;
}
}
// add new images
it = fNewImages.GetIterator();
while (ProfileResultImageType* image = it.Next()) {
if (image->GetImage()->CreationEvent() <= event) {
it.Remove();
int32 deleted = image->GetImage()->DeletionEvent();
if (deleted >= 0 && event >= deleted) {
// image already deleted
delete image;
} else
fImages.Add(image);
}
}
}
template<typename ProfileResultImageType>
ProfileResultImageType*
AbstractProfileResult<ProfileResultImageType>::FindImage(addr_t address) const
{
typename ImageList::ConstIterator it = fImages.GetIterator();
while (ProfileResultImageType* image = it.Next()) {
if (image->ContainsAddress(address))
return image;
}
return NULL;
}
template<typename ProfileResultImageType>
int32
AbstractProfileResult<ProfileResultImageType>::GetHitImages(
ProfileResultImageType** images) const
{
int32 imageCount = 0;
typename ImageList::ConstIterator it = fOldImages.GetIterator();
while (ProfileResultImageType* image = it.Next()) {
if (image->TotalHits() > 0)
images[imageCount++] = image;
}
it = fImages.GetIterator();
while (ProfileResultImageType* image = it.Next()) {
if (image->TotalHits() > 0)
images[imageCount++] = image;
}
return imageCount;
}
#endif // PROFILE_RESULT_H
+12
View File
@@ -0,0 +1,12 @@
/*
* Copyright 2010, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "ProfiledEntity.h"
ProfiledEntity::~ProfiledEntity()
{
}
+22
View File
@@ -0,0 +1,22 @@
/*
* Copyright 2010, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef PROFILED_ENTITY_H
#define PROFILED_ENTITY_H
#include <SupportDefs.h>
class ProfiledEntity {
public:
virtual ~ProfiledEntity();
virtual int32 EntityID() const = 0;
virtual const char* EntityName() const = 0;
virtual const char* EntityType() const = 0;
};
#endif // PROFILED_ENTITY_H
+2 -2
View File
@@ -104,7 +104,7 @@ status_t
Team::InitThread(Thread* thread) Team::InitThread(Thread* thread)
{ {
// The thread // The thread
thread->ProfileResult()->SetLazyImages(!_SynchronousProfiling()); thread->GetProfileResult()->SetLazyImages(!_SynchronousProfiling());
// create the sample area // create the sample area
char areaName[B_OS_NAME_LENGTH]; char areaName[B_OS_NAME_LENGTH];
@@ -267,7 +267,7 @@ Team::_RemoveImage(int32 index, int32 event)
if (_SynchronousProfiling()) { if (_SynchronousProfiling()) {
ThreadList::Iterator it = fThreads.GetIterator(); ThreadList::Iterator it = fThreads.GetIterator();
while (Thread* thread = it.Next()) while (Thread* thread = it.Next())
thread->ProfileResult()->RemoveImage(image); thread->GetProfileResult()->RemoveImage(image);
} else { } else {
// Note: We don't tell the threads that the image has been removed. They // Note: We don't tell the threads that the image has been removed. They
// will be updated lazily when their next profiler update arrives. This // will be updated lazily when their next profiler update arrives. This
+24 -60
View File
@@ -1,8 +1,9 @@
/* /*
* Copyright 2008-2009, Ingo Weinhold, [email protected]. * Copyright 2008-2010, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include "Thread.h" #include "Thread.h"
#include <algorithm> #include <algorithm>
@@ -16,33 +17,6 @@
#include "Team.h" #include "Team.h"
// #pragma mark - ThreadImage
ThreadImage::ThreadImage(Image* image)
:
fImage(image),
fTotalHits(0)
{
fImage->AddReference();
}
ThreadImage::~ThreadImage()
{
fImage->RemoveReference();
}
status_t
ThreadImage::Init()
{
return B_OK;
}
// #pragma mark - Thread
Thread::Thread(thread_id threadID, const char* name, Team* team) Thread::Thread(thread_id threadID, const char* name, Team* team)
: :
@@ -65,8 +39,29 @@ Thread::~Thread()
} }
int32
Thread::EntityID() const
{
return ID();
}
const char*
Thread::EntityName() const
{
return Name();
}
const char*
Thread::EntityType() const
{
return "thread";
}
void void
Thread::SetProfileResult(ThreadProfileResult* result) Thread::SetProfileResult(ProfileResult* result)
{ {
delete fProfileResult; delete fProfileResult;
fProfileResult = result; fProfileResult = result;
@@ -150,34 +145,3 @@ Thread::PrintResults() const
{ {
fProfileResult->PrintResults(); fProfileResult->PrintResults();
} }
// #pragma mark - ThreadProfileResult
ThreadProfileResult::ThreadProfileResult()
:
fThread(NULL),
fInterval(1)
{
}
ThreadProfileResult::~ThreadProfileResult()
{
}
status_t
ThreadProfileResult::Init(Thread* thread)
{
fThread = thread;
return B_OK;
}
void
ThreadProfileResult::SetInterval(bigtime_t interval)
{
fInterval = interval;
}
+14 -259
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2008-2009, Ingo Weinhold, [email protected]. * Copyright 2008-2010, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef THREAD_H #ifndef THREAD_H
@@ -10,47 +10,30 @@
#include <util/DoublyLinkedList.h> #include <util/DoublyLinkedList.h>
#include "Image.h" #include "ProfiledEntity.h"
#include "ProfileResult.h"
class Team; class Team;
class ThreadImage;
class ThreadProfileResult;
class ThreadImage { class Thread : public ProfiledEntity, public DoublyLinkedListLinkImpl<Thread> {
public:
ThreadImage(Image* image);
virtual ~ThreadImage();
virtual status_t Init();
inline image_id ID() const;
inline Image* GetImage() const;
inline bool ContainsAddress(addr_t address) const;
inline int64 TotalHits() const;
protected:
Image* fImage;
int64 fTotalHits;
};
class Thread : public DoublyLinkedListLinkImpl<Thread> {
public: public:
Thread(thread_id threadID, const char* name, Thread(thread_id threadID, const char* name,
Team* team); Team* team);
~Thread(); virtual ~Thread();
inline thread_id ID() const; inline thread_id ID() const;
inline const char* Name() const; inline const char* Name() const;
inline addr_t* Samples() const; inline addr_t* Samples() const;
inline Team* GetTeam() const; inline Team* GetTeam() const;
inline ThreadProfileResult* ProfileResult() const; virtual int32 EntityID() const;
void SetProfileResult(ThreadProfileResult* result); virtual const char* EntityName() const;
virtual const char* EntityType() const;
inline ProfileResult* GetProfileResult() const;
void SetProfileResult(ProfileResult* result);
void UpdateInfo(const char* name); void UpdateInfo(const char* name);
@@ -72,97 +55,10 @@ private:
::Team* fTeam; ::Team* fTeam;
area_id fSampleArea; area_id fSampleArea;
addr_t* fSamples; addr_t* fSamples;
ThreadProfileResult* fProfileResult; ProfileResult* fProfileResult;
}; };
class ThreadProfileResult {
public:
ThreadProfileResult();
virtual ~ThreadProfileResult();
virtual status_t Init(Thread* thread);
void SetInterval(bigtime_t interval);
virtual void SetLazyImages(bool lazy) = 0;
virtual status_t AddImage(Image* image) = 0;
virtual void RemoveImage(Image* image) = 0;
virtual void SynchronizeImages(int32 event) = 0;
virtual void AddSamples(addr_t* samples,
int32 sampleCount) = 0;
virtual void AddDroppedTicks(int32 dropped) = 0;
virtual void PrintResults() = 0;
protected:
Thread* fThread;
bigtime_t fInterval;
};
template<typename ThreadImageType>
class AbstractThreadProfileResult : public ThreadProfileResult {
public:
AbstractThreadProfileResult();
virtual ~AbstractThreadProfileResult();
virtual void SetLazyImages(bool lazy);
virtual status_t AddImage(Image* image);
virtual void RemoveImage(Image* image);
virtual void SynchronizeImages(int32 event);
ThreadImageType* FindImage(addr_t address) const;
int32 GetHitImages(ThreadImageType** images) const;
virtual ThreadImageType* CreateThreadImage(Image* image) = 0;
protected:
typedef DoublyLinkedList<ThreadImageType> ImageList;
ImageList fImages;
ImageList fNewImages;
ImageList fOldImages;
bool fLazyImages;
};
// #pragma mark -
image_id
ThreadImage::ID() const
{
return fImage->ID();
}
bool
ThreadImage::ContainsAddress(addr_t address) const
{
return fImage->ContainsAddress(address);
}
Image*
ThreadImage::GetImage() const
{
return fImage;
}
int64
ThreadImage::TotalHits() const
{
return fTotalHits;
}
// #pragma mark -
thread_id thread_id
Thread::ID() const Thread::ID() const
{ {
@@ -191,8 +87,8 @@ Thread::GetTeam() const
} }
ThreadProfileResult* ProfileResult*
Thread::ProfileResult() const Thread::GetProfileResult() const
{ {
return fProfileResult; return fProfileResult;
} }
@@ -212,145 +108,4 @@ Thread::RemoveImage(Image* image)
} }
// #pragma mark - AbstractThreadProfileResult
template<typename ThreadImageType>
AbstractThreadProfileResult<ThreadImageType>::AbstractThreadProfileResult()
:
fImages(),
fNewImages(),
fOldImages(),
fLazyImages(true)
{
}
template<typename ThreadImageType>
AbstractThreadProfileResult<ThreadImageType>::~AbstractThreadProfileResult()
{
while (ThreadImageType* image = fImages.RemoveHead())
delete image;
while (ThreadImageType* image = fOldImages.RemoveHead())
delete image;
}
template<typename ThreadImageType>
void
AbstractThreadProfileResult<ThreadImageType>::SetLazyImages(bool lazy)
{
fLazyImages = lazy;
}
template<typename ThreadImageType>
status_t
AbstractThreadProfileResult<ThreadImageType>::AddImage(Image* image)
{
ThreadImageType* threadImage = CreateThreadImage(image);
if (threadImage == NULL)
return B_NO_MEMORY;
status_t error = threadImage->Init();
if (error != B_OK) {
delete threadImage;
return error;
}
if (fLazyImages)
fNewImages.Add(threadImage);
else
fImages.Add(threadImage);
return B_OK;
}
template<typename ThreadImageType>
void
AbstractThreadProfileResult<ThreadImageType>::RemoveImage(Image* image)
{
typename ImageList::Iterator it = fImages.GetIterator();
while (ThreadImageType* threadImage = it.Next()) {
if (threadImage->GetImage() == image) {
it.Remove();
if (threadImage->TotalHits() > 0)
fOldImages.Add(threadImage);
else
delete threadImage;
break;
}
}
}
template<typename ThreadImageType>
void
AbstractThreadProfileResult<ThreadImageType>::SynchronizeImages(int32 event)
{
// remove obsolete images
typename ImageList::Iterator it = fImages.GetIterator();
while (ThreadImageType* image = it.Next()) {
int32 deleted = image->GetImage()->DeletionEvent();
if (deleted >= 0 && event >= deleted) {
it.Remove();
if (image->TotalHits() > 0)
fOldImages.Add(image);
else
delete image;
}
}
// add new images
it = fNewImages.GetIterator();
while (ThreadImageType* image = it.Next()) {
if (image->GetImage()->CreationEvent() <= event) {
it.Remove();
int32 deleted = image->GetImage()->DeletionEvent();
if (deleted >= 0 && event >= deleted) {
// image already deleted
delete image;
} else
fImages.Add(image);
}
}
}
template<typename ThreadImageType>
ThreadImageType*
AbstractThreadProfileResult<ThreadImageType>::FindImage(addr_t address) const
{
typename ImageList::ConstIterator it = fImages.GetIterator();
while (ThreadImageType* image = it.Next()) {
if (image->ContainsAddress(address))
return image;
}
return NULL;
}
template<typename ThreadImageType>
int32
AbstractThreadProfileResult<ThreadImageType>::GetHitImages(
ThreadImageType** images) const
{
int32 imageCount = 0;
typename ImageList::ConstIterator it = fOldImages.GetIterator();
while (ThreadImageType* image = it.Next()) {
if (image->TotalHits() > 0)
images[imageCount++] = image;
}
it = fImages.GetIterator();
while (ThreadImageType* image = it.Next()) {
if (image->TotalHits() > 0)
images[imageCount++] = image;
}
return imageCount;
}
#endif // THREAD_H #endif // THREAD_H
+9 -9
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2008-2009, Ingo Weinhold, [email protected]. * Copyright 2008-2010, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -30,8 +30,8 @@
#include <util/DoublyLinkedList.h> #include <util/DoublyLinkedList.h>
#include "BasicThreadProfileResult.h" #include "BasicProfileResult.h"
#include "CallgrindThreadProfileResult.h" #include "CallgrindProfileResult.h"
#include "debug_utils.h" #include "debug_utils.h"
#include "Image.h" #include "Image.h"
#include "Options.h" #include "Options.h"
@@ -145,7 +145,7 @@ public:
if (thread == NULL) if (thread == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
status_t error = _CreateThreadProfileResult(thread); status_t error = _CreateProfileResult(thread);
if (error != B_OK) { if (error != B_OK) {
delete thread; delete thread;
return error; return error;
@@ -333,15 +333,15 @@ private:
return B_OK; return B_OK;
} }
status_t _CreateThreadProfileResult(Thread* thread) status_t _CreateProfileResult(Thread* thread)
{ {
ThreadProfileResult* profileResult; ProfileResult* profileResult;
if (gOptions.callgrind_directory != NULL) if (gOptions.callgrind_directory != NULL)
profileResult = new(std::nothrow) CallgrindThreadProfileResult; profileResult = new(std::nothrow) CallgrindProfileResult;
else if (gOptions.analyze_full_stack) else if (gOptions.analyze_full_stack)
profileResult = new(std::nothrow) InclusiveThreadProfileResult; profileResult = new(std::nothrow) InclusiveProfileResult;
else else
profileResult = new(std::nothrow) ExclusiveThreadProfileResult; profileResult = new(std::nothrow) ExclusiveProfileResult;
if (profileResult == NULL) if (profileResult == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;