/*
 * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
 * Distributed under the terms of the MIT License.
 */
 
 
#include "BasicProfileResult.h"
 
#if __GNUC__ > 2
#include <cxxabi.h>
#endif
#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 - BasicImageProfileResult
 
 
BasicImageProfileResult::BasicImageProfileResult(SharedImage* image,
	image_id id)
	:
	ImageProfileResult(image, id),
	fSymbolHits(NULL),
	fUnknownHits(0)
{
}
 
 
BasicImageProfileResult::~BasicImageProfileResult()
{
}
 
 
status_t
BasicImageProfileResult::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
BasicImageProfileResult::AddHit(addr_t address)
{
	int32 symbolIndex = fImage->FindSymbol(address);
	if (symbolIndex < 0)
		return false;
 
	fSymbolHits[symbolIndex]++;
	fTotalHits++;
 
	return true;
}
 
 
void
BasicImageProfileResult::AddUnknownHit()
{
	fUnknownHits++;
	fTotalHits++;
}
 
 
void
BasicImageProfileResult::AddSymbolHit(int32 symbolIndex)
{
	fSymbolHits[symbolIndex]++;
}
 
 
void
BasicImageProfileResult::AddImageHit()
{
	fTotalHits++;
}
 
 
const int64*
BasicImageProfileResult::SymbolHits() const
{
	return fSymbolHits;
}
 
 
int64
BasicImageProfileResult::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(ImageProfileResultContainer* container)
{
	// get hit images
	BasicImageProfileResult* images[container->CountImages()];
	int32 imageCount = GetHitImages(container, images);
 
	// count symbols
	int32 symbolCount = 0;
	for (int32 k = 0; k < imageCount; k++) {
		BasicImageProfileResult* 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++) {
		BasicImageProfileResult* 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++) {
			BasicImageProfileResult* image = images[k];
			fprintf(gOptions.output, "  %10lld  %10lld  %7ld %s\n",
				image->TotalHits(), image->UnknownHits(),
				image->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;
#if __GNUC__ > 2
			int status;
			const char* symbolName = __cxxabiv1::__cxa_demangle(symbol->Name(),
				NULL, NULL, &status);
			if (symbolName == NULL)
				symbolName = symbol->Name();
#else
			const char* symbolName = symbol->Name();
#endif
			fprintf(gOptions.output, "  %10lld  %10lld  %6.2f  %6ld  %s\n",
				hitSymbol.hits, hitSymbol.hits * fInterval,
				100.0 * hitSymbol.hits / totalTicks, hitSymbol.imageID,
				symbolName);
#if __GNUC__ > 2
			if (status == 0)
				free(const_cast<char*>(symbolName));
#endif
		}
	} else
		fprintf(gOptions.output, "  no functions were hit\n");
}
 
 
status_t
BasicProfileResult::GetImageProfileResult(SharedImage* image, image_id id,
	ImageProfileResult*& _imageResult)
{
	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;
}
 
 
// #pragma mark - InclusiveProfileResult
 
 
void
InclusiveProfileResult::AddSamples(ImageProfileResultContainer* container,
	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;
	BasicImageProfileResult* previousImage = NULL;
	int32 previousSymbol = -1;
 
	for (int32 i = 0; i < sampleCount; i++) {
		addr_t address = samples[i];
		addr_t loadDelta;
		BasicImageProfileResult* image = static_cast<BasicImageProfileResult*>(
			container->FindImage(address, loadDelta));
		int32 symbol = -1;
		if (image != NULL) {
			symbol = image->GetImage()->FindSymbol(address - loadDelta);
			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(ImageProfileResultContainer* container,
	addr_t* samples, int32 sampleCount)
{
	BasicImageProfileResult* image = NULL;
		// the image in which we hit a symbol
	BasicImageProfileResult* 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];
		addr_t loadDelta;
		image = static_cast<BasicImageProfileResult*>(
			container->FindImage(address, loadDelta));
		if (image != NULL) {
			if (image->AddHit(address - loadDelta))
				break;
			if (firstImage == NULL)
				firstImage = image;
		}
	}
 
	if (image == NULL) {
		if (firstImage != NULL)
			firstImage->AddUnknownHit();
		else
			fUnkownTicks++;
	}
 
	fTotalTicks++;
	fTotalSampleCount += sampleCount;
}

↑ V576 Incorrect format. Consider checking the sixth actual argument of the 'fprintf' function. The memsize type argument is expected.

↑ V576 Incorrect format. Consider checking the fifth actual argument of the 'fprintf' function. The memsize type argument is expected.