Help those suffering in the Horn of Africa

Profile Lib Source

Prev: Header Next: References
 
/** ----------------------------------------------------------
 * \class VSProfileLib
 *
 * Lighthouse3D
 *
 * VSProfileLib - Very Simple Profile Library
 *
 * Full documentation at
 * http://www.lighthouse3d.com/very-simple-libs
 *
 * Simple profiler class for both CPU and GPU
 *
 * \version 0.2.0
 * uses OpenGL timers
 *
 * version 0.1.0
 * Initial Release
 *
 ---------------------------------------------------------------*/

#include "vsProfileLib.h"

#include <GL/glew.h>
#include <ctime>
#include <stdio.h>

// Declare static variables
std::string VSProfileLib::sDump;
int VSProfileLib::sDisp = 0;
int VSProfileLib::sCurrLevel = -1;
int VSProfileLib::sTotalLevels = 0;
VSProfileLib::level VSProfileLib::sLevels[PROFILE_MAX_LEVELS];
unsigned int VSProfileLib::sBackBuffer = 0;
unsigned int VSProfileLib::sFrontBuffer = 1;

#if VSPL_CLOCK == VSPL_WIN_HIGH_PERFORMANCE_COUNTER
LARGE_INTEGER VSProfileLib::sFreq;
#endif

// Timer function defined apart for easier replacement
void
VSProfileLib::GetTicks(pTime *ticks) {

#if VSPL_CLOCK == VSPL_WIN_HIGH_PERFORMANCE_COUNTER
	LARGE_INTEGER t;
	QueryPerformanceCounter(&t) ;
	*ticks = 1000.0*(pTime)((double)t.QuadPart/
								(double)sFreq.QuadPart);

#elif VSPL_CLOCK == VSPL_C_CLOCK
	*ticks =  (pTime)clock()/VSPL_CLOCK_RATE;

#elif VSPL_CLOCK == VSPL_WIN_SYSTEMTIME
	SYSTEMTIME systemTime;
	GetSystemTime( &systemTime );

	FILETIME fileTime;
	SystemTimeToFileTime( &systemTime, &fileTime );

	ULARGE_INTEGER uli;
	uli.LowPart = fileTime.dwLowDateTime;
	uli.HighPart = fileTime.dwHighDateTime;

	ULONGLONG systemTimeIn_ms( uli.QuadPart/10000 );
	*ticks = (double)systemTimeIn_ms;

#elif VSPL_CLOCK == VSPL_GETTIMEOFDAY
	timeval t2;
	gettimeofday(&t2,NULL);
	*ticks = t2.tv_sec * 1000.0 + t2.tv_usec / 1000.0;
#endif
}

// Constructor
// begin of a profile section
VSProfileLib::VSProfileLib(std::string name, bool profileGL) {

	int found;
	pTime w;
	sCurrLevel++;

#if VSPL_CLOCK == VSPL_WIN_HIGH_PERFORMANCE_COUNTER
	QueryPerformanceFrequency(&sFreq);
#endif

	GetTicks(&w);

	// create new level
	if (sCurrLevel == sTotalLevels) {

		sLevels[sCurrLevel].cursor = -1;
		createNewSection(name, w, profileGL);
		// store the size of the largest section name
		int aux = name.size() ;
		if (aux > sDisp)
			sDisp = aux;
		sTotalLevels++;
	}
	else {
		// search for name and parent
		found = searchSection(name);
		if (found != -1)
			updateSection(found, w);
		else {
			// create new section inside current level
			createNewSection(name, w, profileGL);
			// store the size of the largest section name
			// for report formatting purposes
			int aux = name.size() ;
			if (aux > sDisp)
				sDisp = aux;
		}
	}

}

// End Section
VSProfileLib::~VSProfileLib() {
	// add the time spent in the current section
	accumulate();
	// decrease current level
	sCurrLevel--;
}

//////////////////////////////////////////////////////////////////////
// Instance Methods
//////////////////////////////////////////////////////////////////////

// Create a new profile section
void VSProfileLib::createNewSection(std::string &name, pTime w, bool profileGL) {

	section s;

#if VSPL_PROFILE == VSPL_PROFILE_CPU_AND_GPU
	s.profileGL = profileGL;
#else
	s.profileGL = false;
#endif
	s.parent = (sCurrLevel > 0 ?
		sLevels[sCurrLevel-1].cursor : -1);
	s.name = name;
	s.calls = 1;
	s.totalTime = 0;
	s.totalQueryTime = 0;

	sLevels[sCurrLevel].cursor++;

	if (profileGL) {
		pair p;
		glGenQueries(2, p.queries);
		glQueryCounter(p.queries[0], GL_TIMESTAMP);
		s.queriesGL[sBackBuffer].push_back(p);
	}

	GetTicks(&(s.startTime));
	s.wastedTime = s.startTime - w;
	sLevels[sCurrLevel].sec.push_back(s);
}

// Serach for a profile section
int VSProfileLib::searchSection(std::string &name) {

	int i,max,par;

	max = sLevels[sCurrLevel].sec.size();
	par = (sCurrLevel==0 ? -1 : sLevels[sCurrLevel-1].cursor);

	for(i=0;i<max;i++) {
		if (( name == sLevels[sCurrLevel].sec[i].name)  &&
			(par == sLevels[sCurrLevel].sec[i].parent))
			return(i);
	}
	return(-1);
}

// updates a profile section
void VSProfileLib::updateSection(int cur, pTime w) {

	section *s;

	s = &(sLevels[sCurrLevel].sec[cur]);
	s->calls++;
	sLevels[sCurrLevel].cursor = cur;

	if (s->profileGL) {
		pair p;
		glGenQueries(2, p.queries);
		glQueryCounter(p.queries[0], GL_TIMESTAMP);
		s->queriesGL[sBackBuffer].push_back(p);
	}
	GetTicks(&s->startTime);
	s->wastedTime += s->startTime - w;
}

// accumulates the time spent in the section
void VSProfileLib::accumulate() {

	section *s;
	pTime t,t2;
	GetTicks(&t);

	s = &(sLevels[sCurrLevel].sec[sLevels[sCurrLevel].cursor]);

	if (s->profileGL) {
		glQueryCounter(s->queriesGL[sBackBuffer][s->queriesGL[sBackBuffer].size()-1].queries[1], GL_TIMESTAMP);
	}
	// to measure wasted time when accumulating
	GetTicks(&t2);
	s->wastedTime += (t2-t);
	s->totalTime += (t - s->startTime);

}

//////////////////////////////////////////////////////////////////////
// Class Methods
//////////////////////////////////////////////////////////////////////

// Resets profile stats
void VSProfileLib::Reset() {

	for(int i=0; i < sTotalLevels; ++i) {

		for (unsigned int s = 0; s < sLevels[i].sec.size(); ++s) {
			for (unsigned int k = 0; k < sLevels[i].sec[s].queriesGL[0].size(); ++k) {
				glDeleteQueries(2, sLevels[i].sec[s].queriesGL[0][k].queries);
			}
			for (unsigned int k = 0; k < sLevels[i].sec[s].queriesGL[1].size(); ++k) {
				glDeleteQueries(2, sLevels[i].sec[s].queriesGL[1][k].queries);
			}
		}
		sLevels[i].sec.clear();
	}
	sTotalLevels = 0;
}

// Builds a string, sDump, with the profile report
const std::string &
VSProfileLib::DumpLevels() {

#if VSPL_PROFILE != VSPL_PROFILE_NONE
	int indent = sTotalLevels * LEVEL_INDENT + sDisp;
	char saux[100];

	char t1[5]="Name";
	char t2[7]="#c";
	char t3[9]="#tc";
	char t4[8]="CPU(ms)";
	char t41[8] ="GPU(ms)";
	char t5[3]="wt";

	sDump = "";
	sprintf(saux,"%-*s  %s  %s  %s       %s\n",indent+4,t1,t2,t4,t41,t5);
	sDump += saux;
	sprintf(saux,"---- %*s\n",indent+31,"------------------------------------");
	sDump += saux;

	DumpLevels(0,-1,sLevels[0].sec[0].calls);
#else
	sDump = "";
#endif

	return sDump;
}

// private method to recursively
// build the profile report
void
VSProfileLib::DumpLevels(int l, int p, pTime calls) {

	int siz;
	char a[2] = "";
	char s[200];
	char s2[2000];
	section *sec;

	siz = sLevels[l].sec.size();

	for(int cur = 0; cur < siz; ++cur) {
		sec = &(sLevels[l].sec[cur]);

		if (l==0)
			calls = sec->calls;

		if ((p == -1) || (sec->parent == p)) {

			sprintf(s,"%#*s%s", l * LEVEL_INDENT ," ",sec->name.c_str());

			if (sec->profileGL)
				sprintf(s2,"%-*s %5.0f %8.2f %8.2f %8.2f\n",
					sDisp + sTotalLevels * LEVEL_INDENT + 2,
					s,
					(float)(sec->calls/calls),
					(float)(sec->totalTime)/(calls),
					(sec->totalQueryTime/(1000000.0 /** calls*/)),
					(float)(sec->wastedTime/(calls)));
			else
				sprintf(s2,"%-*s %5.0f %8.2f          %8.2f\n",
					sDisp + sTotalLevels * LEVEL_INDENT + 2,
					s,
					(float)(sec->calls/calls),
					(float)(sec->totalTime)/(calls),
					(float)(sec->wastedTime)/(calls));

			sDump += s2;

			if (l+1 < sTotalLevels)
				DumpLevels(l+1,cur,calls);
		}

	}
}

// Collect Queries results
void
VSProfileLib::CollectQueryResults() {

#if VSPL_PROFILE == VSPL_PROFILE_CPU_AND_GPU
	int siz;
	section *sec;
	int availableEnd = 0;
	GLuint64 timeStart=0, timeEnd = 0;
	unsigned long long int aux = 0;

	for (int l = 0; l < sTotalLevels; ++l) {
		siz = sLevels[l].sec.size();

		for(int cur = 0; cur < siz; ++cur) {
			sec = &(sLevels[l].sec[cur]);

			if (sec->profileGL) {
				sec->totalQueryTime = 0;
				aux = 0;

				for (unsigned int j = 0; j < sec->queriesGL[sFrontBuffer].size(); ++j) {

					glGetQueryObjectui64v(sec->queriesGL[sFrontBuffer][j].queries[0], GL_QUERY_RESULT, &timeStart);
					glGetQueryObjectui64v(sec->queriesGL[sFrontBuffer][j].queries[1], GL_QUERY_RESULT, &timeEnd);
					aux +=  (timeEnd - timeStart);
					glDeleteQueries(2, sec->queriesGL[sFrontBuffer][j].queries);
				}
				sec->totalQueryTime += aux;
				sec->queriesGL[sFrontBuffer].clear();
			}
		}
	}
	// SWAP QUERY BUFFERS
	if (sBackBuffer) {
		sBackBuffer = 0;
		sFrontBuffer = 1;
	}
	else {
		sBackBuffer = 1;
		sFrontBuffer = 0;
	}
#endif
}

 

Prev: Header Next: References
 

Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

© 2012 Lighthouse3d.com Suffusion theme by Sayontan Sinha