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:
+37
-34
@@ -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++) {
|
||||||
+17
-16
@@ -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
|
||||||
+35
-33
@@ -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
|
||||||
+19
-18
@@ -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
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "ProfiledEntity.h"
|
||||||
|
|
||||||
|
|
||||||
|
ProfiledEntity::~ProfiledEntity()
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user