Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- 2018-11-27 classroom refactoring exercise
- - replaced char* with const char* in all arguments
- - removed dependency on "TextBox", replacing it with std::string outputBuffer.
- - inverted needlessly long branches to reduce the amount of nested scopes
- - turned the global functions into static class methods
- - made "internal" functions private
- - changed all const char* arguments to const std::string&
- - fixed smell: multiple output parameters (GetProfileFromHistory(const string&, float*, float*, float*))
- ------by creating a SamplePoint type and making use of structured bindings
- - Changed char* members in ProfileSampleHistory and ProfileSample for std::string
- --- allowing us to remove all strcmp and strln-calls.
- */
- #ifndef _PROFILE_H
- #define _PROFILE_H
- #include <string>
- class Profile {
- struct SamplePoint{
- float ave{ 0 }, min{ 0 }, max{ 0 };
- };
- static void StoreProfileInHistory(const std::string& name, float percent);
- static SamplePoint GetProfileFromHistory(const std::string& name);
- public:
- static void Init(void);
- static void Begin(const std::string& name);
- static void End(const std::string& name);
- static void DumpOutputToBuffer(void);
- static void Draw(void);
- };
- #endif //_PROFILE_H
- /* Copyright (C) Steve Rabin, 2000.
- * All rights reserved worldwide.
- *
- * This software is provided "as is" without express or implied
- * warranties. You may freely copy and compile this source into
- * applications you distribute provided that the copyright text
- * below is included in the resulting source code, for example:
- * "Portions Copyright (C) Steve Rabin, 2000"
- */
- #include "profile.h"
- #include "custom_time.h"
- #include <assert.h>
- #include <string.h>
- #include <stdio.h>
- #include <iostream>
- #include <string>
- #include <sstream>
- #include <iomanip>
- typedef struct {
- bool bValid; //Whether this data is valid
- unsigned int iProfileInstances; //# of times ProfileBegin called
- int iOpenProfiles; //# of times ProfileBegin w/o ProfileEnd
- std::string szName; //Name of sample
- float fStartTime; //The current open profile start time
- float fAccumulator; //All samples this frame added together
- float fChildrenSampleTime; //Time taken by all children
- unsigned int iNumParents; //Number of profile parents
- } ProfileSample;
- typedef struct {
- bool bValid; //Whether the data is valid
- std::string szName; //Name of the sample
- float fAve; //Average time per frame (percentage)
- float fMin; //Minimum time per frame (percentage)
- float fMax; //Maximum time per frame (percentage)
- } ProfileSampleHistory;
- #define NUM_PROFILE_SAMPLES 50
- ProfileSample g_samples[NUM_PROFILE_SAMPLES];
- ProfileSampleHistory g_history[NUM_PROFILE_SAMPLES];
- float g_startProfile = 0.0f;
- float g_endProfile = 0.0f;
- std::string outputBuffer = "";
- void Profile::Init(void) {
- for (unsigned int i = 0; i < NUM_PROFILE_SAMPLES; i++) {
- g_samples[i].bValid = false;
- g_history[i].bValid = false;
- }
- g_startProfile = GetExactTime();
- }
- void Profile::Begin(const std::string& name) {
- unsigned int i = 0;
- while (i < NUM_PROFILE_SAMPLES && g_samples[i].bValid == true) {
- if (g_samples[i].szName == name) {
- //Found the sample
- g_samples[i].iOpenProfiles++;
- g_samples[i].iProfileInstances++;
- g_samples[i].fStartTime = GetExactTime();
- assert(g_samples[i].iOpenProfiles == 1); //max 1 open at once
- return;
- }
- i++;
- }
- if (i >= NUM_PROFILE_SAMPLES) {
- assert(!"Exceeded Max Available Profile Samples");
- return;
- }
- g_samples[i].szName = name;
- g_samples[i].bValid = true;
- g_samples[i].iOpenProfiles = 1;
- g_samples[i].iProfileInstances = 1;
- g_samples[i].fAccumulator = 0.0f;
- g_samples[i].fStartTime = GetExactTime();
- g_samples[i].fChildrenSampleTime = 0.0f;
- }
- void Profile::End(const std::string& name) {
- unsigned int i = 0;
- unsigned int numParents = 0;
- while (i < NUM_PROFILE_SAMPLES && g_samples[i].bValid == true) {
- if (g_samples[i].szName != name) {
- i++;
- continue; // not the sample we want, go to the next
- }
- unsigned int inner = 0;
- int parent = -1;
- float fEndTime = GetExactTime();
- g_samples[i].iOpenProfiles--;
- //Count all parents and find the immediate parent
- while (g_samples[inner].bValid == true) {
- if (g_samples[inner].iOpenProfiles > 0) { //Found a parent (any open profiles are parents)
- numParents++;
- if (parent < 0) { //Replace invalid parent (index)
- parent = inner;
- }
- else if (g_samples[inner].fStartTime >= g_samples[parent].fStartTime) {
- //Replace with more immediate parent
- parent = inner;
- }
- }
- inner++;
- }
- g_samples[i].iNumParents = numParents; //Remember the current number of parents of the sample
- if (parent >= 0) { //Record this time in fChildrenSampleTime (add it in)
- g_samples[parent].fChildrenSampleTime += fEndTime - g_samples[i].fStartTime;
- }
- //Save sample time in accumulator
- g_samples[i].fAccumulator += fEndTime - g_samples[i].fStartTime;
- return;
- }
- }
- void Profile::DumpOutputToBuffer(void) {
- unsigned int i = 0;
- g_endProfile = GetExactTime();
- outputBuffer.clear();
- outputBuffer += " Ave : Min : Max : # : Profile Name\n";
- outputBuffer += "--------------------------------------------\n";
- while (i < NUM_PROFILE_SAMPLES && g_samples[i].bValid == true) {
- unsigned int indent = 0;
- float sampleTime, percentTime;
- char line[256], name[256];
- std::string indentedName;
- char ave[16], min[16], max[16], num[16];
- if (g_samples[i].iOpenProfiles < 0) { assert(!"ProfileEnd() called without a ProfileBegin()"); }
- else if (g_samples[i].iOpenProfiles > 0) { assert(!"ProfileBegin() called without a ProfileEnd()"); }
- sampleTime = g_samples[i].fAccumulator - g_samples[i].fChildrenSampleTime;
- percentTime = (sampleTime / (g_endProfile - g_startProfile)) * 100.0f;
- //Add new measurement into the history and get the ave, min, and max
- StoreProfileInHistory(g_samples[i].szName, percentTime);
- auto [aveTime, minTime, maxTime] = GetProfileFromHistory(g_samples[i].szName);
- //TODO Format the data
- /*std::stringstream output;
- output << std::setprecision(4) <<;*/
- sprintf_s(ave, "%3.1f", aveTime);
- sprintf_s(min, "%3.1f", minTime);
- sprintf_s(max, "%3.1f", maxTime);
- sprintf_s(num, "%3d", g_samples[i].iProfileInstances);
- indentedName = g_samples[i].szName;
- for (indent = 0; indent < g_samples[i].iNumParents; indent++) {
- sprintf_s(name, " %s", indentedName.c_str());
- indentedName = name;
- }
- sprintf_s(line, "%3s : %3s : %3s : %3s : %s\n", ave, min, max, num, indentedName.c_str());
- outputBuffer += line; //Send the line to text buffer
- i++;
- }
- { //Reset samples for next frame
- unsigned int j;
- for (j = 0; j < NUM_PROFILE_SAMPLES; j++) {
- g_samples[j].bValid = false;
- }
- g_startProfile = GetExactTime();
- }
- }
- void Profile::StoreProfileInHistory(const std::string& name, float percent) {
- unsigned int i = 0;
- float oldRatio;
- float newRatio = 0.8f * GetElapsedTime();
- if (newRatio > 1.0f) {
- newRatio = 1.0f;
- }
- oldRatio = 1.0f - newRatio;
- // TODO: replace with std::find
- for (auto& sample : g_history) {
- if (!sample.bValid) {
- break;
- }
- if (sample.szName != name) {
- i++;
- continue;
- }
- //Found the sample
- sample.fAve = (sample.fAve*oldRatio) + (percent*newRatio);
- if (percent > sample.fMax) {
- sample.fMax = percent;
- }
- if (percent < sample.fMin) {
- sample.fMin = percent;
- }
- else {
- sample.fMin = (sample.fMin*oldRatio) + (percent*newRatio);
- }
- if (sample.fMin < 0.0f) {
- sample.fMin = 0.0f;
- }
- else {
- sample.fMax = (sample.fMax*oldRatio) + (percent*newRatio);
- }
- return;
- }
- if (i < NUM_PROFILE_SAMPLES) { //Add to history
- g_history[i].szName = name;
- g_history[i].bValid = true;
- g_history[i].fAve = g_history[i].fMin = g_history[i].fMax = percent;
- }
- else {
- assert(!"Exceeded Max Available Profile Samples!");
- }
- }
- Profile::SamplePoint Profile::GetProfileFromHistory(const std::string& name) {
- SamplePoint result{};
- for (auto& sample : g_history){
- if (sample.bValid == true && sample.szName == name) {
- result.ave = sample.fAve;
- result.max = sample.fMax;
- result.min = sample.fMin;
- return result;
- }
- }
- return result;
- }
- void Profile::Draw(void) {
- std::cout << outputBuffer << '\n';
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement