Author Topic: Timerbar Optimistion Tool update  (Read 2747 times)

0 Members and 1 Guest are viewing this topic.

Offline RandomTiger

  • Senior Member
  • 211
Timerbar Optimistion Tool update
Not sure anyone cares about this but I've updated my timerbar code.
The timerbar code allows you to time parts of the code and see a representation of the times on screen.
If anyone is thinking about optimisation I strongly suggest you use this tool.

Currently it is only supported by DX5 but the main code is totally generic and uses a callback function to
render the bars. So Phreak could put together a OGL version in about 2 mins I reckon.

The code currently commited has a bug that messes up nested checks, I have fixed that and also added push and pop functions for ease of use when nesting checks.

Take it over leave it.

timerbar.h
Code: [Select]

/*
 * Code created by Random Tiger for a Freespace 2 source code project
 *
 * You may not sell or otherwise commercially exploit the source or things you
 * created based on the source.
 *
*/

#ifndef _TIMERBAR_HEADER_
#define _TIMERBAR_HEADER_

const int MAX_NUM_TIMERBARS = 20;

// These functions should never be used directly, always use macros below
void timerbar_start_frame();
void timerbar_end_frame();
void timerbar_set_draw_func(void (*new_draw_func_ptr)(int colour, float x, float y, float w, float h));

void timerbar_push(int value);
void timerbar_pop();

// This function shouldnt not be used any more or it will break push and pop calls
void timerbar_switch_type(int num);

// Only show timer bars if in debug mode in windows unless TIMERBAR_ON compile flag is set
#if (!defined(NDEBUG) && defined(_WIN32)) || defined(TIMERBAR_ON)

#define TIMERBAR_SET_DRAW_FUNC(f) timerbar_set_draw_func(f);
#define TIMERBAR_START_FRAME()    timerbar_start_frame();
#define TIMERBAR_END_FRAME()      timerbar_end_frame();
#define TIMERBAR_SWITCH_TYPE(n)   timerbar_switch_type(n);

#define TIMERBAR_PUSH(v) timerbar_push(v);
#define TIMERBAR_POP()   timerbar_pop();

#else

#define TIMERBAR_SET_DRAW_FUNC(f) ;
#define TIMERBAR_START_FRAME()   ;
#define TIMERBAR_END_FRAME()     ;
#define TIMERBAR_SWITCH_TYPE(n)  ;

#define TIMERBAR_PUSH(v) ;
#define TIMERBAR_POP()   ;

#endif

#endif


timerbar.cpp
Code: [Select]

/*
 * Code created by Random Tiger for a Freespace 2 source code project
 *
 * You may not sell or otherwise commercially exploit the source or things you
 * created based on the source.
 *
*/

/*
 * This module is intended as a debug tool to measure the speed of blocks of code and display
 * that information as coloured bars across the top of the screen.
 *
 * This allows interactive measuring of components of the code, very useful for optimisztion.
 */

#ifdef _WIN32
#include
#include

#include "timerbar.h"

// Internal structure for handling frame data
typedef struct
{
LARGE_INTEGER start_value;
LARGE_INTEGER total_value;

LARGE_INTEGER average;
LARGE_INTEGER frame_total;

} timerbar_profile;

timerbar_profile profiles[MAX_NUM_TIMERBARS];
int timerbar_current_profile = 0;

LARGE_INTEGER timerbar_ultimate_start_value;
LARGE_INTEGER timerbar_last_start_value;

// Data needed for push and pop functionality
const MAX_TB_STACK_SIZE = 100;

int timerbar_stack[MAX_TB_STACK_SIZE];
int timerbar_current_stack_layer = 0;

/*
 *
 *
 *
 */
void timerbar_push(int value)
{
Assert((timerbar_current_stack_layer + 1) < MAX_TB_STACK_SIZE);

timerbar_stack[timerbar_current_stack_layer] = timerbar_current_profile;
timerbar_current_stack_layer++;

timerbar_switch_type(value);
}

/*
 *
 *
 *
 */
void timerbar_pop()
{
timerbar_current_stack_layer--;
Assert(timerbar_current_stack_layer >= 0);

timerbar_switch_type(timerbar_stack[timerbar_current_stack_layer]);
}

// This pointer holds the draw function to use or NULL
void (*draw_func_ptr)(int colour, float x, float y, float w, float h) = NULL;

void timerbar_start_frame()
{
timerbar_current_stack_layer = 0;
timerbar_current_profile     = 0;

if(QueryPerformanceCounter(&timerbar_ultimate_start_value) == FALSE)
{
// DBUGFILE_OUTPUT_0("QueryPerformanceCounter not supported by hardware");
draw_func_ptr = NULL;
}

timerbar_last_start_value = timerbar_ultimate_start_value;

}

// Constants need for timerbar_conv_and_draw calculations
const int WIDTH = 480;
const float WIDTHF = ((float) WIDTH) * 1.01f;

/**
 * Internal conversion function to convert draw data into bars for the screen
 *
 * @param int colour - colour index (>=0)
 * @param int xpos   - x position to start bar on
 * @param int xwidth - width of bar
 * @param int yrow - Index of row bar belongs to
 */
void timerbar_conv_and_draw(int colour, int xpos, int xwidth, int yrow)
{
float fxpos  = (float) xpos;
float fxwidth = (float) xwidth;
 
draw_func_ptr(colour,
fxpos / WIDTHF,
yrow * 0.01f,
fxwidth / WIDTHF,
0.005f);
}

void timerbar_end_frame()
{
// Now we want to draw the bars
if(draw_func_ptr == NULL)
{
// we have not been given a draw function so we are going to have to quit
return;
}

timerbar_switch_type(-1);

int last_xpos = 0;
int y_pos     = 0;


for(int i = 0; i < MAX_NUM_TIMERBARS; i++)
{
// Nothing to render this frame
if(profiles[i].frame_total.QuadPart == 0)
{
continue;
}

int xsize = (int) profiles[i].frame_total.QuadPart / 90;

// break condition in else
while(1)
{
// if bar runs over
if(last_xpos + xsize > WIDTH)
{
int rem_len = WIDTH - last_xpos;

// Draw from current position to the end of the bar
timerbar_conv_and_draw(i, last_xpos, rem_len, y_pos);

xsize -= rem_len;
last_xpos = 0;
y_pos++;
}
else
{
// Draw whats left and break for the next bar
timerbar_conv_and_draw(i,last_xpos, xsize, y_pos);

last_xpos += xsize;
break;
}
}

// reset for next frame
profiles[i].frame_total.QuadPart = 0;
}
}

void timerbar_switch_type(int num)
{
if(num >= MAX_NUM_TIMERBARS)
{
return;
}

// Calculate old profile's total
LARGE_INTEGER now;
if(QueryPerformanceCounter(&now) == FALSE)
{
// DBUGFILE_OUTPUT_0("QueryPerformanceCounter not supported by hardware");
}

profiles[timerbar_current_profile].frame_total.QuadPart +=
(now.QuadPart - timerbar_last_start_value.QuadPart);  

if(num != -1)
{
// Switch to new profile
timerbar_current_profile = num;
}

// Update time to count from
if(QueryPerformanceCounter(&timerbar_last_start_value) == FALSE)
{
// DBUGFILE_OUTPUT_0("QueryPerformanceCounter not supported by hardware");
}
}

/**
 * @param void (*new_draw_func_ptr)(int colour, float x, float y, float w, float h) - pointer to draw function
 *
 * Sets the draw function used to output the timer data, designed to be generic allowing any API
 * to take advantage of this module. Set to NULL to disable drawing.
 *
 * By default the draw function is set to NULL
 */
void timerbar_set_draw_func(void (*new_draw_func_ptr)(int colour, float x, float y, float w, float h))
{
  draw_func_ptr = new_draw_func_ptr;
}

#endif

 
Timerbar Optimistion Tool update
I'm gonna go out on a limb here RT and ask what I hope you were thinking too: Can we throw this into the DX8.1 version of Freespace and hunt down those performance bugs with it? (otherwise I'm gonna have to secure a copy of MSVC++ Professional somehow...)

 

Offline RandomTiger

  • Senior Member
  • 211
Timerbar Optimistion Tool update
Of course, some of the code may already be there,I always meant to put it in but I couldnt lock down that bug, but now its fixed.

Any code I post on these boards Im happy to be used for just about anything as long as I get credit for it. My names in fs2_open, Im happy, do what you want. :)

Though Im not sure we really need to look for whats making it slow:

1. Being in special mode to allow access to back buffer for software fogging
2. Rendering lots of small shapes in an unoptimal way, given what daveb and DX8sdk help says this all fits.
« Last Edit: January 14, 2003, 07:10:59 am by 848 »

 
Timerbar Optimistion Tool update
I know about the possible slow downs, but I'm a seeing-is-believing person. That and I'm also just curious as to where the rest of the time gets spent.

We need to get on with a merge of the DX8 code, but unfortunately that would be very painful without broadband....:mad:

 

Offline Inquisitor

Timerbar Optimistion Tool update
I have been mucking with the merge, might get some help with it from WM, but it would be nice if UP were back ;)
No signature.

 

Offline Bobboau

  • Just a MODern kinda guy
    Just MODerately cool
    And MODest too
  • 213
Timerbar Optimistion Tool update
so how do you use these?
I realy could use them for finding were my decal code is slowest at
Bobboau, bringing you products that work... in theory
learn to use PCS
creator of the ProXimus Procedural Texture and Effect Generator
My latest build of PCS2, get it while it's hot!
PCS 2.0.3


DEUTERONOMY 22:11
Thou shalt not wear a garment of diverse sorts, [as] of woollen and linen together

 

Offline RandomTiger

  • Senior Member
  • 211
Timerbar Optimistion Tool update
If you are testing with D3D then half of it is in place already. TIMERBAR_START_FRAME and TIMERBAR_END_FRAME should be in the correct place. Do a search for TIMERBAR_SWITCH() calls and get rid of them (except in timerbar.cpp of course).

The switch system works but is not very helpful if you need to nest. Give that some functions maybe called directly or through other functions its best to use proper nesting functions, _PUSH and _POP.

ie:
Code: [Select]

void function1()
{
         blah blah blah
         // 0 is already being used to measure the rest of the frame rate so use something greater
         TIMERBAR_PUSH(1);
         blah blah blah
        another_function();

         TIMERBAR_POP();
         blah blah blah
}

void another_function()
{
         blah blah blah
         TIMERBAR_PUSH(2);
         blah blah blah

         TIMERBAR_POP();
         blah blah blah
}



Also of course remember to put the code at the beginning of this thread int fs2_open otherwise you'll be usin a old nasty buggy system.

You will also have to update the number of colours in the D3D code, easy stuff. Finally you may get a compile error because I think I changed the name of a constant to MAX_NUM_TIMERBARS bt its all simple stuff to fix up.

Hope that helps.
« Last Edit: January 25, 2003, 01:19:30 pm by 848 »

 

Offline Bobboau

  • Just a MODern kinda guy
    Just MODerately cool
    And MODest too
  • 213
Timerbar Optimistion Tool update
so
TIMERBAR_PUSH(int);
starts timeing something
TIMERBAR_POP();
stops timeing the most recent bar
Bobboau, bringing you products that work... in theory
learn to use PCS
creator of the ProXimus Procedural Texture and Effect Generator
My latest build of PCS2, get it while it's hot!
PCS 2.0.3


DEUTERONOMY 22:11
Thou shalt not wear a garment of diverse sorts, [as] of woollen and linen together

 

Offline RandomTiger

  • Senior Member
  • 211
Timerbar Optimistion Tool update
Yep, its fairly simple, I suggest that you start with a small number of bars to start with while you get used to it and make sure its all setup right.

Also remember sometimes various codepaths are missed out depending on whats onscreen so bars may disappear as well as becoming very thin.

Whatever else is happening the total area of the bars should be representitive of whats going on.

Really you just need to get in there and have a play around with it.