* Made ProfileResult and ImageProfileResults BReferenceable.
* Added command line option '-S', which triggers a new summary mode. When enabled the image/symbol hits aren't counted for individual threads anymore, but summed up for all threads. The results are printed at the end. Works together with all profiling modes (inclusive, exclusive, callgrind). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35573 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
a2ce05945a
commit
28f8887517
@ -220,10 +220,23 @@ BasicProfileResult::PrintResults(ImageProfileResultContainer* container)
|
||||
}
|
||||
|
||||
|
||||
ImageProfileResult*
|
||||
BasicProfileResult::CreateImageProfileResult(SharedImage* image, image_id id)
|
||||
status_t
|
||||
BasicProfileResult::GetImageProfileResult(SharedImage* image, image_id id,
|
||||
ImageProfileResult*& _imageResult)
|
||||
{
|
||||
return new(std::nothrow) BasicImageProfileResult(image, id);
|
||||
BasicImageProfileResult* result
|
||||
= new(std::nothrow) BasicImageProfileResult(image, id);
|
||||
if (result == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t error = result->Init();
|
||||
if (error != B_OK) {
|
||||
delete result;
|
||||
return error;
|
||||
}
|
||||
|
||||
_imageResult = result;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -16,7 +16,7 @@ public:
|
||||
image_id id);
|
||||
virtual ~BasicImageProfileResult();
|
||||
|
||||
virtual status_t Init();
|
||||
status_t Init();
|
||||
|
||||
inline bool AddHit(addr_t address);
|
||||
inline void AddUnknownHit();
|
||||
@ -40,8 +40,9 @@ public:
|
||||
virtual void PrintResults(
|
||||
ImageProfileResultContainer* container);
|
||||
|
||||
virtual ImageProfileResult* CreateImageProfileResult(SharedImage* image,
|
||||
image_id id);
|
||||
virtual status_t GetImageProfileResult(SharedImage* image,
|
||||
image_id id,
|
||||
ImageProfileResult*& _imageResult);
|
||||
|
||||
protected:
|
||||
int64 fTotalTicks;
|
||||
|
@ -262,11 +262,23 @@ CallgrindProfileResult::PrintResults(ImageProfileResultContainer* container)
|
||||
}
|
||||
|
||||
|
||||
ImageProfileResult*
|
||||
CallgrindProfileResult::CreateImageProfileResult(SharedImage* image,
|
||||
image_id id)
|
||||
status_t
|
||||
CallgrindProfileResult::GetImageProfileResult(SharedImage* image, image_id id,
|
||||
ImageProfileResult*& _imageResult)
|
||||
{
|
||||
return new(std::nothrow) CallgrindImageProfileResult(image, id);
|
||||
CallgrindImageProfileResult* result
|
||||
= new(std::nothrow) CallgrindImageProfileResult(image, id);
|
||||
if (result == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t error = result->Init();
|
||||
if (error != B_OK) {
|
||||
delete result;
|
||||
return error;
|
||||
}
|
||||
|
||||
_imageResult = result;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -46,7 +46,7 @@ public:
|
||||
image_id id);
|
||||
virtual ~CallgrindImageProfileResult();
|
||||
|
||||
virtual status_t Init();
|
||||
status_t Init();
|
||||
|
||||
inline void AddSymbolHit(int32 symbolIndex,
|
||||
CallgrindImageProfileResult* calledImage,
|
||||
@ -74,8 +74,9 @@ public:
|
||||
virtual void PrintResults(
|
||||
ImageProfileResultContainer* container);
|
||||
|
||||
virtual ImageProfileResult* CreateImageProfileResult(SharedImage* image,
|
||||
image_id id);
|
||||
virtual status_t GetImageProfileResult(SharedImage* image,
|
||||
image_id id,
|
||||
ImageProfileResult*& _imageResult);
|
||||
|
||||
private:
|
||||
void _PrintFunction(FILE* out,
|
||||
|
@ -16,6 +16,7 @@ BinCommand profile
|
||||
ProfiledEntity.cpp
|
||||
ProfileResult.cpp
|
||||
SharedImage.cpp
|
||||
SummaryProfileResult.cpp
|
||||
Team.cpp
|
||||
Thread.cpp
|
||||
profile.cpp
|
||||
|
@ -23,7 +23,8 @@ struct Options {
|
||||
profile_loading(false),
|
||||
profile_teams(true),
|
||||
profile_threads(true),
|
||||
analyze_full_stack(false)
|
||||
analyze_full_stack(false),
|
||||
summary_result(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -37,6 +38,7 @@ struct Options {
|
||||
bool profile_teams;
|
||||
bool profile_threads;
|
||||
bool analyze_full_stack;
|
||||
bool summary_result;
|
||||
};
|
||||
|
||||
|
||||
|
@ -6,6 +6,8 @@
|
||||
#define PROFILE_RESULT_H
|
||||
|
||||
|
||||
#include <Referenceable.h>
|
||||
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
#include "SharedImage.h"
|
||||
@ -15,7 +17,7 @@ class ProfiledEntity;
|
||||
class Team;
|
||||
|
||||
|
||||
class ImageProfileResult {
|
||||
class ImageProfileResult : public BReferenceable {
|
||||
public:
|
||||
ImageProfileResult(SharedImage* image,
|
||||
image_id id);
|
||||
@ -58,13 +60,15 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class ProfileResult {
|
||||
class ProfileResult : public BReferenceable {
|
||||
public:
|
||||
ProfileResult();
|
||||
virtual ~ProfileResult();
|
||||
|
||||
virtual status_t Init(ProfiledEntity* entity);
|
||||
|
||||
ProfiledEntity* Entity() const { return fEntity; }
|
||||
|
||||
void SetInterval(bigtime_t interval);
|
||||
|
||||
virtual void AddSamples(
|
||||
@ -75,8 +79,9 @@ public:
|
||||
virtual void PrintResults(
|
||||
ImageProfileResultContainer* container) = 0;
|
||||
|
||||
virtual ImageProfileResult* CreateImageProfileResult(SharedImage* image,
|
||||
image_id id) = 0;
|
||||
virtual status_t GetImageProfileResult(SharedImage* image,
|
||||
image_id id,
|
||||
ImageProfileResult*& _imageResult) = 0;
|
||||
|
||||
protected:
|
||||
template<typename ImageProfileResultType>
|
||||
|
148
src/bin/debug/profile/SummaryProfileResult.cpp
Normal file
148
src/bin/debug/profile/SummaryProfileResult.cpp
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "SummaryProfileResult.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
|
||||
// #pragma mark - SummaryImage
|
||||
|
||||
|
||||
SummaryImage::SummaryImage(ImageProfileResult* result)
|
||||
:
|
||||
fResult(result)
|
||||
{
|
||||
fResult->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
SummaryImage::~SummaryImage()
|
||||
{
|
||||
fResult->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - SummaryProfileResult
|
||||
|
||||
|
||||
SummaryProfileResult::SummaryProfileResult(ProfileResult* result)
|
||||
:
|
||||
fResult(result),
|
||||
fNextImageID(1)
|
||||
{
|
||||
fResult->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
SummaryProfileResult::~SummaryProfileResult()
|
||||
{
|
||||
fResult->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
SummaryProfileResult::Init(ProfiledEntity* entity)
|
||||
{
|
||||
status_t error = ProfileResult::Init(entity);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
error = fImages.Init();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SummaryProfileResult::AddSamples(ImageProfileResultContainer* container,
|
||||
addr_t* samples, int32 sampleCount)
|
||||
{
|
||||
fResult->AddSamples(container, samples, sampleCount);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SummaryProfileResult::AddDroppedTicks(int32 dropped)
|
||||
{
|
||||
fResult->AddDroppedTicks(dropped);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SummaryProfileResult::PrintResults(ImageProfileResultContainer* container)
|
||||
{
|
||||
// This is called for individual threads. We only print results in
|
||||
// PrintSummaryResults(), though.
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SummaryProfileResult::PrintSummaryResults()
|
||||
{
|
||||
fResult->PrintResults(this);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
SummaryProfileResult::GetImageProfileResult(SharedImage* image, image_id id,
|
||||
ImageProfileResult*& _imageResult)
|
||||
{
|
||||
// Check whether we do already know the image.
|
||||
SummaryImage* summaryImage = fImages.Lookup(image);
|
||||
if (summaryImage == NULL) {
|
||||
// nope, create it
|
||||
ImageProfileResult* imageResult;
|
||||
status_t error = fResult->GetImageProfileResult(image, fNextImageID++,
|
||||
imageResult);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
BReference<ImageProfileResult> imageResultReference(imageResult, true);
|
||||
|
||||
summaryImage = new(std::nothrow) SummaryImage(imageResult);
|
||||
if (summaryImage == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
fImages.Insert(summaryImage);
|
||||
}
|
||||
|
||||
_imageResult = summaryImage->Result();
|
||||
_imageResult->AcquireReference();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
SummaryProfileResult::CountImages() const
|
||||
{
|
||||
return fImages.CountElements();
|
||||
}
|
||||
|
||||
|
||||
ImageProfileResult*
|
||||
SummaryProfileResult::VisitImages(Visitor& visitor) const
|
||||
{
|
||||
for (ImageTable::Iterator it = fImages.GetIterator();
|
||||
SummaryImage* image = it.Next();) {
|
||||
if (visitor.VisitImage(image->Result()))
|
||||
return image->Result();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
ImageProfileResult*
|
||||
SummaryProfileResult::FindImage(addr_t address, addr_t& _loadDelta) const
|
||||
{
|
||||
// We cannot and don't need to implement this. It's only relevant for
|
||||
// AddSamples(), where we use the caller's container implementation.
|
||||
return NULL;
|
||||
}
|
94
src/bin/debug/profile/SummaryProfileResult.h
Normal file
94
src/bin/debug/profile/SummaryProfileResult.h
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef SUMMARY_PROFILE_RESULT_H
|
||||
#define SUMMARY_PROFILE_RESULT_H
|
||||
|
||||
|
||||
#include <util/OpenHashTable.h>
|
||||
|
||||
#include "ProfileResult.h"
|
||||
|
||||
|
||||
class SummaryImage {
|
||||
public:
|
||||
SummaryImage(ImageProfileResult* result);
|
||||
~SummaryImage();
|
||||
|
||||
ImageProfileResult* Result() const { return fResult; }
|
||||
SharedImage* GetImage() const { return fResult->GetImage(); }
|
||||
|
||||
SummaryImage*& HashNext() { return fHashNext; }
|
||||
|
||||
private:
|
||||
ImageProfileResult* fResult;
|
||||
SummaryImage* fHashNext;
|
||||
};
|
||||
|
||||
|
||||
struct SummaryImageHashDefinition {
|
||||
typedef SharedImage* KeyType;
|
||||
typedef SummaryImage ValueType;
|
||||
|
||||
size_t HashKey(SharedImage* key) const
|
||||
{
|
||||
return (addr_t)key / (2 * sizeof(void*));
|
||||
}
|
||||
|
||||
size_t Hash(SummaryImage* value) const
|
||||
{
|
||||
return HashKey(value->GetImage());
|
||||
}
|
||||
|
||||
bool Compare(SharedImage* key, SummaryImage* value) const
|
||||
{
|
||||
return value->GetImage() == key;
|
||||
}
|
||||
|
||||
SummaryImage*& GetLink(SummaryImage* value) const
|
||||
{
|
||||
return value->HashNext();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class SummaryProfileResult : public ProfileResult,
|
||||
private ImageProfileResultContainer {
|
||||
public:
|
||||
SummaryProfileResult(ProfileResult* result);
|
||||
virtual ~SummaryProfileResult();
|
||||
|
||||
virtual status_t Init(ProfiledEntity* entity);
|
||||
|
||||
virtual void AddSamples(
|
||||
ImageProfileResultContainer* container,
|
||||
addr_t* samples, int32 sampleCount);
|
||||
virtual void AddDroppedTicks(int32 dropped);
|
||||
virtual void PrintResults(
|
||||
ImageProfileResultContainer* container);
|
||||
|
||||
virtual status_t GetImageProfileResult(SharedImage* image,
|
||||
image_id id,
|
||||
ImageProfileResult*& _imageResult);
|
||||
|
||||
void PrintSummaryResults();
|
||||
|
||||
private:
|
||||
typedef BOpenHashTable<SummaryImageHashDefinition> ImageTable;
|
||||
|
||||
private:
|
||||
// ImageProfileResultContainer
|
||||
virtual int32 CountImages() const;
|
||||
virtual ImageProfileResult* VisitImages(Visitor& visitor) const;
|
||||
virtual ImageProfileResult* FindImage(addr_t address,
|
||||
addr_t& _loadDelta) const;
|
||||
|
||||
private:
|
||||
ProfileResult* fResult;
|
||||
ImageTable fImages;
|
||||
image_id fNextImageID;
|
||||
};
|
||||
|
||||
|
||||
#endif // SUMMARY_PROFILE_RESULT_H
|
@ -27,13 +27,14 @@ ThreadImage::ThreadImage(Image* image, ImageProfileResult* result)
|
||||
fResult(result)
|
||||
{
|
||||
fImage->AcquireReference();
|
||||
fResult->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
ThreadImage::~ThreadImage()
|
||||
{
|
||||
fImage->ReleaseReference();
|
||||
delete fResult;
|
||||
fResult->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
@ -58,7 +59,8 @@ Thread::~Thread()
|
||||
if (fSampleArea >= 0)
|
||||
delete_area(fSampleArea);
|
||||
|
||||
delete fProfileResult;
|
||||
if (fProfileResult != NULL)
|
||||
fProfileResult->ReleaseReference();
|
||||
|
||||
while (ThreadImage* image = fImages.RemoveHead())
|
||||
delete image;
|
||||
@ -91,8 +93,14 @@ Thread::EntityType() const
|
||||
void
|
||||
Thread::SetProfileResult(ProfileResult* result)
|
||||
{
|
||||
delete fProfileResult;
|
||||
ProfileResult* oldResult = fProfileResult;
|
||||
|
||||
fProfileResult = result;
|
||||
if (fProfileResult != NULL)
|
||||
fProfileResult->AcquireReference();
|
||||
|
||||
if (oldResult)
|
||||
oldResult->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
@ -128,22 +136,17 @@ Thread::SetLazyImages(bool lazy)
|
||||
status_t
|
||||
Thread::AddImage(Image* image)
|
||||
{
|
||||
ImageProfileResult* result = fProfileResult->CreateImageProfileResult(
|
||||
image->GetSharedImage(), image->ID());
|
||||
if (result == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t error = result->Init();
|
||||
if (error != B_OK) {
|
||||
delete result;
|
||||
ImageProfileResult* result;
|
||||
status_t error = fProfileResult->GetImageProfileResult(
|
||||
image->GetSharedImage(), image->ID(), result);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
}
|
||||
|
||||
BReference<ImageProfileResult> resultReference(result, true);
|
||||
|
||||
ThreadImage* threadImage = new(std::nothrow) ThreadImage(image, result);
|
||||
if (threadImage == NULL) {
|
||||
delete result;
|
||||
if (threadImage == NULL)
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (fLazyImages)
|
||||
fNewImages.Add(threadImage);
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "debug_utils.h"
|
||||
#include "Image.h"
|
||||
#include "Options.h"
|
||||
#include "SummaryProfileResult.h"
|
||||
#include "Team.h"
|
||||
|
||||
|
||||
@ -84,6 +85,8 @@ static const char* kUsage =
|
||||
" caller stack per tick. If the topmost address doesn't\n"
|
||||
" hit a known image, the next address will be matched\n"
|
||||
" (and so on).\n"
|
||||
" -S - Don't output results for individual threads, but\n"
|
||||
" produce a combined output at the end.\n"
|
||||
" -v <directory> - Create valgrind/callgrind output. <directory> is the\n"
|
||||
" directory where to put the output files.\n"
|
||||
;
|
||||
@ -94,22 +97,46 @@ Options gOptions;
|
||||
static bool sCaughtDeadlySignal = false;
|
||||
|
||||
|
||||
class ThreadManager {
|
||||
class ThreadManager : private ProfiledEntity {
|
||||
public:
|
||||
ThreadManager(port_id debuggerPort)
|
||||
:
|
||||
fTeams(20, true),
|
||||
fThreads(20, true),
|
||||
fKernelTeam(NULL),
|
||||
fDebuggerPort(debuggerPort)
|
||||
fDebuggerPort(debuggerPort),
|
||||
fSummaryProfileResult(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
~ThreadManager()
|
||||
virtual ~ThreadManager()
|
||||
{
|
||||
// release image references
|
||||
for (ImageMap::iterator it = fImages.begin(); it != fImages.end(); ++it)
|
||||
it->second->RemoveReference();
|
||||
|
||||
if (fSummaryProfileResult != NULL)
|
||||
fSummaryProfileResult->ReleaseReference();
|
||||
}
|
||||
|
||||
status_t Init()
|
||||
{
|
||||
if (!gOptions.summary_result)
|
||||
return B_OK;
|
||||
|
||||
ProfileResult* profileResult;
|
||||
status_t error = _CreateProfileResult(this, profileResult);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
BReference<ProfileResult> profileResultReference(profileResult, true);
|
||||
|
||||
fSummaryProfileResult = new(std::nothrow) SummaryProfileResult(
|
||||
profileResult);
|
||||
if (fSummaryProfileResult == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
return fSummaryProfileResult->Init(profileResult->Entity());
|
||||
}
|
||||
|
||||
status_t AddTeam(team_id teamID, Team** _team = NULL)
|
||||
@ -145,7 +172,7 @@ public:
|
||||
if (thread == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t error = _CreateProfileResult(thread);
|
||||
status_t error = _CreateThreadProfileResult(thread);
|
||||
if (error != B_OK) {
|
||||
delete thread;
|
||||
return error;
|
||||
@ -244,6 +271,28 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void PrintSummaryResults()
|
||||
{
|
||||
if (fSummaryProfileResult != NULL)
|
||||
fSummaryProfileResult->PrintSummaryResults();
|
||||
}
|
||||
|
||||
private:
|
||||
virtual int32 EntityID() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual const char* EntityName() const
|
||||
{
|
||||
return "all";
|
||||
}
|
||||
|
||||
virtual const char* EntityType() const
|
||||
{
|
||||
return "summary";
|
||||
}
|
||||
|
||||
private:
|
||||
status_t _AddTeam(team_id teamID, system_profiler_team_added* addedInfo,
|
||||
Team** _team = NULL)
|
||||
@ -333,9 +382,28 @@ private:
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t _CreateProfileResult(Thread* thread)
|
||||
status_t _CreateThreadProfileResult(Thread* thread)
|
||||
{
|
||||
if (fSummaryProfileResult != NULL) {
|
||||
thread->SetProfileResult(fSummaryProfileResult);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
ProfileResult* profileResult;
|
||||
status_t error = _CreateProfileResult(thread, profileResult);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
thread->SetProfileResult(profileResult);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t _CreateProfileResult(ProfiledEntity* profiledEntity,
|
||||
ProfileResult*& _profileResult)
|
||||
{
|
||||
ProfileResult* profileResult;
|
||||
|
||||
if (gOptions.callgrind_directory != NULL)
|
||||
profileResult = new(std::nothrow) CallgrindProfileResult;
|
||||
else if (gOptions.analyze_full_stack)
|
||||
@ -346,13 +414,13 @@ private:
|
||||
if (profileResult == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t error = profileResult->Init(thread);
|
||||
if (error != B_OK) {
|
||||
delete profileResult;
|
||||
return error;
|
||||
}
|
||||
BReference<ProfileResult> profileResultReference(profileResult, true);
|
||||
|
||||
thread->SetProfileResult(profileResult);
|
||||
status_t error = profileResult->Init(profiledEntity);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
_profileResult = profileResultReference.Detach();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -412,6 +480,7 @@ private:
|
||||
ImageMap fImages;
|
||||
Team* fKernelTeam;
|
||||
port_id fDebuggerPort;
|
||||
SummaryProfileResult* fSummaryProfileResult;
|
||||
};
|
||||
|
||||
|
||||
@ -608,6 +677,12 @@ profile_all(const char* const* programArgs, int programArgCount)
|
||||
|
||||
// create a thread manager
|
||||
ThreadManager threadManager(-1); // TODO: We don't need a debugger port!
|
||||
status_t error = threadManager.Init();
|
||||
if (error != B_OK) {
|
||||
fprintf(stderr, "%s: Failed to init thread manager: %s\n", kCommandName,
|
||||
strerror(error));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// start profiling
|
||||
system_profiler_parameters profilerParameters;
|
||||
@ -618,7 +693,7 @@ profile_all(const char* const* programArgs, int programArgCount)
|
||||
profilerParameters.interval = gOptions.interval;
|
||||
profilerParameters.stack_depth = gOptions.stack_depth;
|
||||
|
||||
status_t error = _kern_system_profiler_start(&profilerParameters);
|
||||
error = _kern_system_profiler_start(&profilerParameters);
|
||||
if (error != B_OK) {
|
||||
fprintf(stderr, "%s: Failed to start profiling: %s\n", kCommandName,
|
||||
strerror(error));
|
||||
@ -678,6 +753,8 @@ profile_all(const char* const* programArgs, int programArgCount)
|
||||
Thread* thread = threadManager.ThreadAt(i);
|
||||
thread->PrintResults();
|
||||
}
|
||||
|
||||
threadManager.PrintSummaryResults();
|
||||
}
|
||||
|
||||
|
||||
@ -686,10 +763,10 @@ dump_recorded()
|
||||
{
|
||||
// retrieve recorded samples and parameters
|
||||
system_profiler_parameters profilerParameters;
|
||||
status_t status = _kern_system_profiler_recorded(&profilerParameters);
|
||||
if (status != B_OK) {
|
||||
status_t error = _kern_system_profiler_recorded(&profilerParameters);
|
||||
if (error != B_OK) {
|
||||
fprintf(stderr, "%s: Failed to get recorded profiling buffer: %s\n",
|
||||
kCommandName, strerror(status));
|
||||
kCommandName, strerror(error));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -699,10 +776,10 @@ dump_recorded()
|
||||
|
||||
// create an area for the sample buffer
|
||||
area_info info;
|
||||
status = get_area_info(profilerParameters.buffer_area, &info);
|
||||
if (status != B_OK) {
|
||||
error = get_area_info(profilerParameters.buffer_area, &info);
|
||||
if (error != B_OK) {
|
||||
fprintf(stderr, "%s: Recorded profiling buffer invalid: %s\n",
|
||||
kCommandName, strerror(status));
|
||||
kCommandName, strerror(error));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -714,6 +791,12 @@ dump_recorded()
|
||||
|
||||
// create a thread manager
|
||||
ThreadManager threadManager(-1); // TODO: We don't need a debugger port!
|
||||
error = threadManager.Init();
|
||||
if (error != B_OK) {
|
||||
fprintf(stderr, "%s: Failed to init thread manager: %s\n", kCommandName,
|
||||
strerror(error));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// get the current buffer
|
||||
size_t bufferStart = bufferHeader->start;
|
||||
@ -736,6 +819,8 @@ dump_recorded()
|
||||
Thread* thread = threadManager.ThreadAt(i);
|
||||
thread->PrintResults();
|
||||
}
|
||||
|
||||
threadManager.PrintSummaryResults();
|
||||
}
|
||||
|
||||
|
||||
@ -771,6 +856,13 @@ profile_single(const char* const* programArgs, int programArgCount)
|
||||
|
||||
// add team and thread to the thread manager
|
||||
ThreadManager threadManager(debuggerPort);
|
||||
error = threadManager.Init();
|
||||
if (error != B_OK) {
|
||||
fprintf(stderr, "%s: Failed to init thread manager: %s\n", kCommandName,
|
||||
strerror(error));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (threadManager.AddTeam(teamID) != B_OK
|
||||
|| threadManager.AddThread(threadID) != B_OK) {
|
||||
exit(1);
|
||||
@ -882,6 +974,9 @@ profile_single(const char* const* programArgs, int programArgCount)
|
||||
if (message.origin.thread >= 0 && message.origin.nub_port >= 0)
|
||||
continue_thread(message.origin.nub_port, message.origin.thread);
|
||||
}
|
||||
|
||||
// prints summary results
|
||||
threadManager.PrintSummaryResults();
|
||||
}
|
||||
|
||||
|
||||
@ -901,7 +996,7 @@ main(int argc, const char* const* argv)
|
||||
};
|
||||
|
||||
opterr = 0; // don't print errors
|
||||
int c = getopt_long(argc, (char**)argv, "+acCfhi:klo:rs:v:",
|
||||
int c = getopt_long(argc, (char**)argv, "+acCfhi:klo:rsS:v:",
|
||||
sLongOptions, NULL);
|
||||
if (c == -1)
|
||||
break;
|
||||
@ -941,6 +1036,9 @@ main(int argc, const char* const* argv)
|
||||
case 's':
|
||||
stackDepth = atol(optarg);
|
||||
break;
|
||||
case 'S':
|
||||
gOptions.summary_result = true;
|
||||
break;
|
||||
case 'v':
|
||||
gOptions.callgrind_directory = optarg;
|
||||
gOptions.analyze_full_stack = true;
|
||||
|
Loading…
Reference in New Issue
Block a user