Author: bonefish Date: 2010-02-20 21:31:04 +0100 (Sat, 20 Feb 2010) New Revision: 35546 Changeset: http://dev.haiku-os.org/changeset/35546/haiku Added: haiku/trunk/src/bin/debug/profile/BasicProfileResult.cpp haiku/trunk/src/bin/debug/profile/BasicProfileResult.h haiku/trunk/src/bin/debug/profile/CallgrindProfileResult.cpp haiku/trunk/src/bin/debug/profile/CallgrindProfileResult.h haiku/trunk/src/bin/debug/profile/ProfileResult.cpp haiku/trunk/src/bin/debug/profile/ProfileResult.h haiku/trunk/src/bin/debug/profile/ProfiledEntity.cpp haiku/trunk/src/bin/debug/profile/ProfiledEntity.h Removed: haiku/trunk/src/bin/debug/profile/BasicThreadProfileResult.cpp haiku/trunk/src/bin/debug/profile/BasicThreadProfileResult.h haiku/trunk/src/bin/debug/profile/CallgrindThreadProfileResult.cpp haiku/trunk/src/bin/debug/profile/CallgrindThreadProfileResult.h Modified: haiku/trunk/src/bin/debug/profile/Jamfile haiku/trunk/src/bin/debug/profile/Team.cpp haiku/trunk/src/bin/debug/profile/Thread.cpp haiku/trunk/src/bin/debug/profile/Thread.h haiku/trunk/src/bin/debug/profile/profile.cpp Log: 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. Copied: haiku/trunk/src/bin/debug/profile/BasicProfileResult.cpp (from rev 35519, haiku/trunk/src/bin/debug/profile/BasicThreadProfileResult.cpp) =================================================================== --- haiku/trunk/src/bin/debug/profile/BasicProfileResult.cpp (rev 0) +++ haiku/trunk/src/bin/debug/profile/BasicProfileResult.cpp 2010-02-20 20:31:04 UTC (rev 35546) @@ -0,0 +1,303 @@ +/* + * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@xxxxxxx + * Distributed under the terms of the MIT License. + */ + + +#include "BasicProfileResult.h" + +#include <stdio.h> + +#include <algorithm> +#include <new> + +#include "Options.h" +#include "ProfiledEntity.h" + + +struct HitSymbol { + int64 hits; + Symbol* symbol; + image_id imageID; + + inline bool operator<(const HitSymbol& other) const + { + return hits > other.hits; + } +}; + + +// #pragma mark - BasicProfileResultImage + + +BasicProfileResultImage::BasicProfileResultImage(Image* image) + : + ProfileResultImage(image), + fSymbolHits(NULL), + fUnknownHits(0) +{ +} + + +BasicProfileResultImage::~BasicProfileResultImage() +{ +} + + +status_t +BasicProfileResultImage::Init() +{ + int32 symbolCount = fImage->SymbolCount(); + fSymbolHits = new(std::nothrow) int64[symbolCount]; + if (fSymbolHits == NULL) + return B_NO_MEMORY; + + memset(fSymbolHits, 0, 8 * symbolCount); + + return B_OK; +} + + +bool +BasicProfileResultImage::AddHit(addr_t address) +{ + int32 symbolIndex = fImage->FindSymbol(address); + if (symbolIndex < 0) + return false; + + fSymbolHits[symbolIndex]++; + fTotalHits++; + + return true; +} + + +void +BasicProfileResultImage::AddUnknownHit() +{ + fUnknownHits++; + fTotalHits++; +} + + +void +BasicProfileResultImage::AddSymbolHit(int32 symbolIndex) +{ + fSymbolHits[symbolIndex]++; +} + + +void +BasicProfileResultImage::AddImageHit() +{ + fTotalHits++; +} + + +const int64* +BasicProfileResultImage::SymbolHits() const +{ + return fSymbolHits; +} + + +int64 +BasicProfileResultImage::UnknownHits() const +{ + return fUnknownHits; +} + + +// #pragma mark - BasicProfileResult + + +BasicProfileResult::BasicProfileResult() + : + fTotalTicks(0), + fUnkownTicks(0), + fDroppedTicks(0), + fTotalSampleCount(0) +{ +} + + +void +BasicProfileResult::AddDroppedTicks(int32 dropped) +{ + fDroppedTicks += dropped; +} + + +void +BasicProfileResult::PrintResults() +{ + // get hit images + BasicProfileResultImage* images[fOldImages.Count() + fImages.Count()]; + int32 imageCount = GetHitImages(images); + + // count symbols + int32 symbolCount = 0; + for (int32 k = 0; k < imageCount; k++) { + BasicProfileResultImage* image = images[k]; + if (image->TotalHits() > image->UnknownHits()) + symbolCount += image->GetImage()->SymbolCount(); + } + + // find and sort the hit symbols + HitSymbol hitSymbols[symbolCount]; + int32 hitSymbolCount = 0; + + for (int32 k = 0; k < imageCount; k++) { + BasicProfileResultImage* image = images[k]; + if (image->TotalHits() > image->UnknownHits()) { + Symbol** symbols = image->GetImage()->Symbols(); + const int64* symbolHits = image->SymbolHits(); + int32 imageSymbolCount = image->GetImage()->SymbolCount(); + for (int32 i = 0; i < imageSymbolCount; i++) { + if (symbolHits[i] > 0) { + HitSymbol& hitSymbol = hitSymbols[hitSymbolCount++]; + hitSymbol.hits = symbolHits[i]; + hitSymbol.symbol = symbols[i]; + hitSymbol.imageID = image->ID(); + } + } + } + } + + if (hitSymbolCount > 1) + std::sort(hitSymbols, hitSymbols + hitSymbolCount); + + int64 totalTicks = fTotalTicks; + fprintf(gOptions.output, "\nprofiling results for %s \"%s\" " + "(%" B_PRId32 "):\n", fEntity->EntityType(), fEntity->EntityName(), + fEntity->EntityID()); + fprintf(gOptions.output, " tick interval: %lld us\n", fInterval); + fprintf(gOptions.output, " total ticks: %lld (%lld us)\n", + totalTicks, totalTicks * fInterval); + if (totalTicks == 0) + totalTicks = 1; + fprintf(gOptions.output, " unknown ticks: %lld (%lld us, %6.2f%%)\n", + fUnkownTicks, fUnkownTicks * fInterval, + 100.0 * fUnkownTicks / totalTicks); + fprintf(gOptions.output, " dropped ticks: %lld (%lld us, %6.2f%%)\n", + fDroppedTicks, fDroppedTicks * fInterval, + 100.0 * fDroppedTicks / totalTicks); + if (gOptions.analyze_full_stack) { + fprintf(gOptions.output, " samples/tick: %.1f\n", + (double)fTotalSampleCount / totalTicks); + } + + if (imageCount > 0) { + fprintf(gOptions.output, "\n"); + fprintf(gOptions.output, " hits unknown image\n"); + fprintf(gOptions.output, " ---------------------------------------" + "---------------------------------------\n"); + for (int32 k = 0; k < imageCount; k++) { + BasicProfileResultImage* image = images[k]; + fprintf(gOptions.output, " %10lld %10lld %7ld %s\n", + image->TotalHits(), image->UnknownHits(), + image->GetImage()->ID(), image->GetImage()->Name()); + } + } + + if (hitSymbolCount > 0) { + fprintf(gOptions.output, "\n"); + fprintf(gOptions.output, " hits in us in %% " + "image function\n"); + fprintf(gOptions.output, " ---------------------------------------" + "---------------------------------------\n"); + for (int32 i = 0; i < hitSymbolCount; i++) { + const HitSymbol& hitSymbol = hitSymbols[i]; + const Symbol* symbol = hitSymbol.symbol; + fprintf(gOptions.output, " %10lld %10lld %6.2f %6ld %s\n", + hitSymbol.hits, hitSymbol.hits * fInterval, + 100.0 * hitSymbol.hits / totalTicks, hitSymbol.imageID, + symbol->Name()); + } + } else + fprintf(gOptions.output, " no functions were hit\n"); +} + + +BasicProfileResultImage* +BasicProfileResult::CreateProfileResultImage(Image* image) +{ + return new(std::nothrow) BasicProfileResultImage(image); +} + + +// #pragma mark - InclusiveProfileResult + + +void +InclusiveProfileResult::AddSamples(addr_t* samples, int32 sampleCount) +{ + // Sort the samples. This way hits of the same symbol are + // successive and we can avoid incrementing the hit count of the + // same symbol twice. Same for images. + std::sort(samples, samples + sampleCount); + + int32 unknownSamples = 0; + BasicProfileResultImage* previousImage = NULL; + int32 previousSymbol = -1; + + for (int32 i = 0; i < sampleCount; i++) { + addr_t address = samples[i]; + BasicProfileResultImage* image = FindImage(address); + int32 symbol = -1; + if (image != NULL) { + symbol = image->GetImage()->FindSymbol(address); + if (symbol < 0) { + // TODO: Count unknown image hits? + } else if (image != previousImage || symbol != previousSymbol) + image->AddSymbolHit(symbol); + + if (image != previousImage) + image->AddImageHit(); + } else + unknownSamples++; + + previousImage = image; + previousSymbol = symbol; + } + + if (unknownSamples == sampleCount) + fUnkownTicks++; + + fTotalTicks++; + fTotalSampleCount += sampleCount; +} + + +// #pragma mark - ExclusiveProfileResult + + +void +ExclusiveProfileResult::AddSamples(addr_t* samples, int32 sampleCount) +{ + BasicProfileResultImage* image = NULL; + // the image in which we hit a symbol + BasicProfileResultImage* firstImage = NULL; + // the first image we hit, != image if no symbol was hit + + for (int32 k = 0; k < sampleCount; k++) { + addr_t address = samples[k]; + image = FindImage(address); + if (image != NULL) { + if (image->AddHit(address)) + break; + if (firstImage == NULL) + firstImage = image; + } + } + + if (image == NULL) { + if (firstImage != NULL) + firstImage->AddUnknownHit(); + else + fUnkownTicks++; + } + + fTotalTicks++; + fTotalSampleCount += sampleCount; +} Copied: haiku/trunk/src/bin/debug/profile/BasicProfileResult.h (from rev 35519, haiku/trunk/src/bin/debug/profile/BasicThreadProfileResult.h) =================================================================== --- haiku/trunk/src/bin/debug/profile/BasicProfileResult.h (rev 0) +++ haiku/trunk/src/bin/debug/profile/BasicProfileResult.h 2010-02-20 20:31:04 UTC (rev 35546) @@ -0,0 +1,66 @@ +/* + * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@xxxxxxx + * Distributed under the terms of the MIT License. + */ +#ifndef BASIC_PROFILE_RESULT_H +#define BASIC_PROFILE_RESULT_H + + +#include "ProfileResult.h" + + +class BasicProfileResultImage : public ProfileResultImage, + public DoublyLinkedListLinkImpl<BasicProfileResultImage> { +public: + BasicProfileResultImage(Image* image); + virtual ~BasicProfileResultImage(); + + virtual status_t Init(); + + inline bool AddHit(addr_t address); + inline void AddUnknownHit(); + inline void AddSymbolHit(int32 symbolIndex); + inline void AddImageHit(); + + inline const int64* SymbolHits() const; + inline int64 UnknownHits() const; + +private: + int64* fSymbolHits; + int64 fUnknownHits; +}; + + +class BasicProfileResult + : public AbstractProfileResult<BasicProfileResultImage> { +public: + BasicProfileResult(); + + virtual void AddDroppedTicks(int32 dropped); + virtual void PrintResults(); + + virtual BasicProfileResultImage* CreateProfileResultImage(Image* image); + +protected: + int64 fTotalTicks; + int64 fUnkownTicks; + int64 fDroppedTicks; + int64 fTotalSampleCount; +}; + + +class InclusiveProfileResult : public BasicProfileResult { +public: + virtual void AddSamples(addr_t* samples, + int32 sampleCount); +}; + + +class ExclusiveProfileResult : public BasicProfileResult { +public: + virtual void AddSamples(addr_t* samples, + int32 sampleCount); +}; + + +#endif // BASIC_PROFILE_RESULT_H Copied: haiku/trunk/src/bin/debug/profile/CallgrindProfileResult.cpp (from rev 35519, haiku/trunk/src/bin/debug/profile/CallgrindThreadProfileResult.cpp) =================================================================== --- haiku/trunk/src/bin/debug/profile/CallgrindProfileResult.cpp (rev 0) +++ haiku/trunk/src/bin/debug/profile/CallgrindProfileResult.cpp 2010-02-20 20:31:04 UTC (rev 35546) @@ -0,0 +1,293 @@ +/* + * Copyright 2010, Ingo Weinhold, ingo_weinhold@xxxxxxx + * Distributed under the terms of the MIT License. + */ + + +#include "CallgrindProfileResult.h" + +#include <errno.h> +#include <sys/stat.h> + +#include <algorithm> +#include <new> + +#include "Options.h" +#include "ProfiledEntity.h" + + +// #pragma mark - CallgrindProfileResultImage + + +CallgrindProfileResultImage::CallgrindProfileResultImage(Image* image) + : + ProfileResultImage(image), + fFunctions(NULL), + fOutputIndex(0) +{ +} + + +CallgrindProfileResultImage::~CallgrindProfileResultImage() +{ + int32 symbolCount = fImage->SymbolCount(); + for (int32 i = 0; i < symbolCount; i++) { + while (CallgrindCalledFunction* calledFunction + = fFunctions[i].calledFunctions) { + fFunctions[i].calledFunctions = calledFunction->next; + delete calledFunction; + } + } + + delete[] fFunctions; +} + + +status_t +CallgrindProfileResultImage::Init() +{ + int32 symbolCount = fImage->SymbolCount(); + fFunctions = new(std::nothrow) CallgrindFunction[symbolCount]; + if (fFunctions == NULL) + return B_NO_MEMORY; + + memset(fFunctions, 0, sizeof(CallgrindFunction) * symbolCount); + + return B_OK; +} + + +void +CallgrindProfileResultImage::AddSymbolHit(int32 symbolIndex, + CallgrindProfileResultImage* calledImage, int32 calledSymbol) + +{ + fTotalHits++; + + CallgrindFunction& function = fFunctions[symbolIndex]; + if (calledImage != NULL) { + // check whether the called function is known already + CallgrindCalledFunction* calledFunction = function.calledFunctions; + while (calledFunction != NULL) { + if (calledFunction->image == calledImage + && calledFunction->function == calledSymbol) { + break; + } + calledFunction = calledFunction->next; + } + + // create a new CallgrindCalledFunction object, if not known + if (calledFunction == NULL) { + calledFunction = new(std::nothrow) CallgrindCalledFunction( + calledImage, calledSymbol); + if (calledFunction == NULL) + return; + + calledFunction->next = function.calledFunctions; + function.calledFunctions = calledFunction; + } + + calledFunction->hits++; + } else + function.hits++; +} + + +CallgrindFunction* +CallgrindProfileResultImage::Functions() const +{ + return fFunctions; +} + + +int32 +CallgrindProfileResultImage::OutputIndex() const +{ + return fOutputIndex; +} + + +void +CallgrindProfileResultImage::SetOutputIndex(int32 index) +{ + fOutputIndex = index; +} + + +// #pragma mark - CallgrindProfileResult + + +CallgrindProfileResult::CallgrindProfileResult() + : + fTotalTicks(0), + fUnkownTicks(0), + fDroppedTicks(0), + fNextImageOutputIndex(1), + fNextFunctionOutputIndex(1) +{ +} + + +void +CallgrindProfileResult::AddSamples(addr_t* samples, int32 sampleCount) +{ + int32 unknownSamples = 0; + CallgrindProfileResultImage* previousImage = NULL; + int32 previousSymbol = -1; + + // TODO: That probably doesn't work with recursive functions. + for (int32 i = 0; i < sampleCount; i++) { + addr_t address = samples[i]; + CallgrindProfileResultImage* image = FindImage(address); + int32 symbol = -1; + if (image != NULL) { + symbol = image->GetImage()->FindSymbol(address); + if (symbol >= 0) { + image->AddSymbolHit(symbol, previousImage, previousSymbol); + previousImage = image; + previousSymbol = symbol; + } + } else + unknownSamples++; + } + + if (unknownSamples == sampleCount) + fUnkownTicks++; + + fTotalTicks++; +} + + +void +CallgrindProfileResult::AddDroppedTicks(int32 dropped) +{ + fDroppedTicks += dropped; +} + + +void +CallgrindProfileResult::PrintResults() +{ + // create output file + + // create output dir + mkdir(gOptions.callgrind_directory, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + + // get the entity name and replace slashes by hyphens + char entityName[B_OS_NAME_LENGTH]; + strlcpy(entityName, fEntity->EntityName(), sizeof(entityName)); + char* slash = entityName; + while ((slash = strchr(slash, '/')) != NULL) + *slash = '-'; + + // create the file name + char fileName[B_PATH_NAME_LENGTH]; + snprintf(fileName, sizeof(fileName), "%s/callgrind.out.%ld.%s.%lldms", + gOptions.callgrind_directory, fEntity->EntityID(), entityName, + fTotalTicks * fInterval); + + // create the file + FILE* out = fopen(fileName, "w+"); + if (out == NULL) { + fprintf(stderr, "%s: Failed to open output file \"%s\": %s\n", + kCommandName, fileName, strerror(errno)); + return; + } + + // write the header + fprintf(out, "version: 1\n"); + fprintf(out, "creator: Haiku profile\n"); + fprintf(out, "pid: %ld\n", fEntity->EntityID()); + fprintf(out, "cmd: %s\n", fEntity->EntityName()); + fprintf(out, "part: 1\n\n"); + + fprintf(out, "positions: line\n"); + fprintf(out, "events: Ticks Time\n"); + fprintf(out, "summary: %lld %lld\n", fTotalTicks, fTotalTicks * fInterval); + + // get hit images + CallgrindProfileResultImage* images[fOldImages.Count() + fImages.Count()]; + int32 imageCount = GetHitImages(images); + + for (int32 i = 0; i < imageCount; i++) { + CallgrindProfileResultImage* image = images[i]; + + CallgrindFunction* functions = image->Functions(); + int32 imageSymbolCount = image->GetImage()->SymbolCount(); + for (int32 k = 0; k < imageSymbolCount; k++) { + CallgrindFunction& function = functions[k]; + if (function.hits == 0 && function.calledFunctions == NULL) + continue; + + fprintf(out, "\n"); + _PrintFunction(out, image, k, false); + fprintf(out, "0 %lld %lld\n", function.hits, + function.hits * fInterval); + + CallgrindCalledFunction* calledFunction = function.calledFunctions; + while (calledFunction != NULL) { + _PrintFunction(out, calledFunction->image, + calledFunction->function, true); + fprintf(out, "calls=%lld 0\n", calledFunction->hits); + fprintf(out, "0 %lld %lld\n", calledFunction->hits, + calledFunction->hits * fInterval); + calledFunction = calledFunction->next; + } + } + } + + // print pseudo-functions for unknown and dropped ticks + if (fUnkownTicks + fDroppedTicks > 0) { + fprintf(out, "\nob=<pseudo>\n"); + + if (fUnkownTicks > 0) { + fprintf(out, "\nfn=unknown\n"); + fprintf(out, "0 %lld\n", fUnkownTicks); + } + + if (fDroppedTicks > 0) { + fprintf(out, "\nfn=dropped\n"); + fprintf(out, "0 %lld\n", fDroppedTicks); + } + } + + fprintf(out, "\ntotals: %lld %lld\n", fTotalTicks, fTotalTicks * fInterval); + + fclose(out); +} + + +CallgrindProfileResultImage* +CallgrindProfileResult::CreateProfileResultImage(Image* image) +{ + return new(std::nothrow) CallgrindProfileResultImage(image); +} + + +void +CallgrindProfileResult::_PrintFunction(FILE* out, + CallgrindProfileResultImage* image, int32 functionIndex, bool called) +{ + if (image->OutputIndex() == 0) { + // need to print the image name + int32 index = fNextImageOutputIndex++; + image->SetOutputIndex(index); + fprintf(out, "%sob=(%ld) %s:%ld\n", called ? "c" : "", index, + image->GetImage()->Name(), image->ID()); + } else { + // image is already known + // TODO: We may not need to print it at all! + fprintf(out, "%sob=(%ld)\n", called ? "c" : "", image->OutputIndex()); + } + + CallgrindFunction& function = image->Functions()[functionIndex]; + if (function.outputIndex == 0) { + // need to print the function name + function.outputIndex = fNextFunctionOutputIndex++; + fprintf(out, "%sfn=(%ld) %s\n", called ? "c" : "", function.outputIndex, + image->GetImage()->Symbols()[functionIndex]->Name()); + } else { + // function is already known + fprintf(out, "%sfn=(%ld)\n", called ? "c" : "", function.outputIndex); + } +} Copied: haiku/trunk/src/bin/debug/profile/CallgrindProfileResult.h (from rev 35519, haiku/trunk/src/bin/debug/profile/CallgrindThreadProfileResult.h) =================================================================== --- haiku/trunk/src/bin/debug/profile/CallgrindProfileResult.h (rev 0) +++ haiku/trunk/src/bin/debug/profile/CallgrindProfileResult.h 2010-02-20 20:31:04 UTC (rev 35546) @@ -0,0 +1,90 @@ +/* + * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@xxxxxxx + * Distributed under the terms of the MIT License. + */ +#ifndef CALLGRIND_PROFILE_RESULT_H +#define CALLGRIND_PROFILE_RESULT_H + + +#include <stdio.h> + +#include "ProfileResult.h" + + +class CallgrindProfileResultImage; + + +struct CallgrindCalledFunction { + CallgrindCalledFunction* next; + CallgrindProfileResultImage* image; + int32 function; + int64 hits; + + CallgrindCalledFunction(CallgrindProfileResultImage* image, int32 function) + : + next(NULL), + image(image), + function(function), + hits(0) + { + } +}; + + +struct CallgrindFunction { + int64 hits; + CallgrindCalledFunction* calledFunctions; + int32 outputIndex; + // index when generating the output file +}; + + +class CallgrindProfileResultImage : public ProfileResultImage, + public DoublyLinkedListLinkImpl<CallgrindProfileResultImage> { +public: + CallgrindProfileResultImage(Image* image); + virtual ~CallgrindProfileResultImage(); + + virtual status_t Init(); + + inline void AddSymbolHit(int32 symbolIndex, + CallgrindProfileResultImage* calledImage, + int32 calledSymbol); + + inline CallgrindFunction* Functions() const; + + inline int32 OutputIndex() const; + inline void SetOutputIndex(int32 index); + +private: + CallgrindFunction* fFunctions; + int32 fOutputIndex; +}; + + +class CallgrindProfileResult + : public AbstractProfileResult<CallgrindProfileResultImage> { +public: + CallgrindProfileResult(); + + virtual void AddSamples(addr_t* samples, + int32 sampleCount); + virtual void AddDroppedTicks(int32 dropped); + virtual void PrintResults(); + + virtual CallgrindProfileResultImage* CreateProfileResultImage(Image* image); + +private: + void _PrintFunction(FILE* out, + CallgrindProfileResultImage* image, + int32 functionIndex, bool called); +private: + int64 fTotalTicks; + int64 fUnkownTicks; + int64 fDroppedTicks; + int32 fNextImageOutputIndex; + int32 fNextFunctionOutputIndex; +}; + + +#endif // CALLGRIND_PROFILE_RESULT_H Modified: haiku/trunk/src/bin/debug/profile/Jamfile =================================================================== --- haiku/trunk/src/bin/debug/profile/Jamfile 2010-02-20 19:53:48 UTC (rev 35545) +++ haiku/trunk/src/bin/debug/profile/Jamfile 2010-02-20 20:31:04 UTC (rev 35546) @@ -10,9 +10,11 @@ BinCommand profile : - BasicThreadProfileResult.cpp - CallgrindThreadProfileResult.cpp + BasicProfileResult.cpp + CallgrindProfileResult.cpp Image.cpp + ProfiledEntity.cpp + ProfileResult.cpp SharedImage.cpp Team.cpp Thread.cpp Added: haiku/trunk/src/bin/debug/profile/ProfileResult.cpp =================================================================== --- haiku/trunk/src/bin/debug/profile/ProfileResult.cpp (rev 0) +++ haiku/trunk/src/bin/debug/profile/ProfileResult.cpp 2010-02-20 20:31:04 UTC (rev 35546) @@ -0,0 +1,63 @@ +/* + * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@xxxxxxx + * 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; +} Added: haiku/trunk/src/bin/debug/profile/ProfileResult.h =================================================================== --- haiku/trunk/src/bin/debug/profile/ProfileResult.h (rev 0) +++ haiku/trunk/src/bin/debug/profile/ProfileResult.h 2010-02-20 20:31:04 UTC (rev 35546) @@ -0,0 +1,265 @@ +/* + * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@xxxxxxx + * 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(), [... truncated: 701 lines follow ...]