ulfben

Classroom refactoring exercise (day 1)

Nov 27th, 2018
135
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. 2018-11-27 classroom refactoring exercise
  3. - replaced char* with const char* in all arguments
  4. - removed dependency on "TextBox", replacing it with std::string outputBuffer.
  5. - inverted needlessly long branches to reduce the amount of nested scopes
  6. - turned the global functions into static class methods
  7. - made "internal" functions private
  8. - changed all const char* arguments to const std::string&
  9. - fixed smell: multiple output parameters (GetProfileFromHistory(const string&, float*, float*, float*))
  10. ------by creating a SamplePoint type and making use of structured bindings
  11. - Changed char* members in ProfileSampleHistory and ProfileSample for std::string
  12. --- allowing us to remove all strcmp and strln-calls.
  13. */
  14. #ifndef _PROFILE_H
  15. #define _PROFILE_H
  16. #include <string>
  17. class Profile {
  18.     struct SamplePoint{
  19.         float ave{ 0 }, min{ 0 }, max{ 0 };
  20.     };
  21.     static void StoreProfileInHistory(const std::string& name, float percent);
  22.     static SamplePoint GetProfileFromHistory(const std::string& name);
  23. public:
  24.     static void Init(void);
  25.     static void Begin(const std::string& name);
  26.     static void End(const std::string& name);
  27.     static void DumpOutputToBuffer(void);
  28.     static void Draw(void);
  29. };
  30. #endif //_PROFILE_H
  31.  
  32. /* Copyright (C) Steve Rabin, 2000.
  33.  * All rights reserved worldwide.
  34.  *
  35.  * This software is provided "as is" without express or implied
  36.  * warranties. You may freely copy and compile this source into
  37.  * applications you distribute provided that the copyright text
  38.  * below is included in the resulting source code, for example:
  39.  * "Portions Copyright (C) Steve Rabin, 2000"
  40.  */
  41. #include "profile.h"
  42. #include "custom_time.h"
  43. #include <assert.h>
  44. #include <string.h>
  45. #include <stdio.h>
  46. #include <iostream>
  47. #include <string>
  48. #include <sstream>
  49. #include <iomanip>
  50. typedef struct {
  51.     bool bValid;                 //Whether this data is valid
  52.     unsigned int iProfileInstances;      //# of times ProfileBegin called
  53.     int iOpenProfiles;           //# of times ProfileBegin w/o ProfileEnd
  54.     std::string szName;            //Name of sample
  55.     float fStartTime;            //The current open profile start time
  56.     float fAccumulator;          //All samples this frame added together
  57.     float fChildrenSampleTime;   //Time taken by all children
  58.     unsigned int iNumParents;            //Number of profile parents
  59. } ProfileSample;
  60.  
  61. typedef struct {
  62.     bool bValid;        //Whether the data is valid
  63.     std::string szName;   //Name of the sample
  64.     float fAve;         //Average time per frame (percentage)
  65.     float fMin;         //Minimum time per frame (percentage)
  66.     float fMax;         //Maximum time per frame (percentage)
  67. } ProfileSampleHistory;
  68.  
  69. #define NUM_PROFILE_SAMPLES 50
  70. ProfileSample g_samples[NUM_PROFILE_SAMPLES];
  71. ProfileSampleHistory g_history[NUM_PROFILE_SAMPLES];
  72. float g_startProfile = 0.0f;
  73. float g_endProfile = 0.0f;
  74. std::string outputBuffer = "";
  75.  
  76. void Profile::Init(void) {
  77.     for (unsigned int i = 0; i < NUM_PROFILE_SAMPLES; i++) {
  78.         g_samples[i].bValid = false;
  79.         g_history[i].bValid = false;
  80.     }
  81.     g_startProfile = GetExactTime();
  82. }
  83.  
  84. void Profile::Begin(const std::string& name) {
  85.     unsigned int i = 0;
  86.     while (i < NUM_PROFILE_SAMPLES && g_samples[i].bValid == true) {
  87.         if (g_samples[i].szName == name) {
  88.             //Found the sample
  89.             g_samples[i].iOpenProfiles++;
  90.             g_samples[i].iProfileInstances++;
  91.             g_samples[i].fStartTime = GetExactTime();
  92.             assert(g_samples[i].iOpenProfiles == 1); //max 1 open at once
  93.             return;
  94.         }
  95.         i++;
  96.     }
  97.  
  98.     if (i >= NUM_PROFILE_SAMPLES) {
  99.         assert(!"Exceeded Max Available Profile Samples");
  100.         return;
  101.     }
  102.  
  103.     g_samples[i].szName = name;
  104.     g_samples[i].bValid = true;
  105.     g_samples[i].iOpenProfiles = 1;
  106.     g_samples[i].iProfileInstances = 1;
  107.     g_samples[i].fAccumulator = 0.0f;
  108.     g_samples[i].fStartTime = GetExactTime();
  109.     g_samples[i].fChildrenSampleTime = 0.0f;
  110. }
  111.  
  112.  
  113. void Profile::End(const std::string& name) {
  114.     unsigned int i = 0;
  115.     unsigned int numParents = 0;
  116.     while (i < NUM_PROFILE_SAMPLES && g_samples[i].bValid == true) {
  117.         if (g_samples[i].szName != name) {
  118.             i++;
  119.             continue; // not the sample we want, go to the next
  120.         }
  121.         unsigned int inner = 0;
  122.         int parent = -1;
  123.         float fEndTime = GetExactTime();
  124.         g_samples[i].iOpenProfiles--;
  125.  
  126.         //Count all parents and find the immediate parent
  127.         while (g_samples[inner].bValid == true) {
  128.             if (g_samples[inner].iOpenProfiles > 0) {  //Found a parent (any open profiles are parents)
  129.                 numParents++;
  130.                 if (parent < 0) {  //Replace invalid parent (index)
  131.                     parent = inner;
  132.                 }
  133.                 else if (g_samples[inner].fStartTime >= g_samples[parent].fStartTime) {
  134.                     //Replace with more immediate parent
  135.                     parent = inner;
  136.                 }
  137.             }
  138.             inner++;
  139.         }
  140.         g_samples[i].iNumParents = numParents; //Remember the current number of parents of the sample
  141.  
  142.         if (parent >= 0) {  //Record this time in fChildrenSampleTime (add it in)
  143.             g_samples[parent].fChildrenSampleTime += fEndTime - g_samples[i].fStartTime;
  144.         }
  145.         //Save sample time in accumulator
  146.         g_samples[i].fAccumulator += fEndTime - g_samples[i].fStartTime;
  147.         return;
  148.     }
  149. }
  150.  
  151. void Profile::DumpOutputToBuffer(void) {
  152.     unsigned int i = 0;
  153.     g_endProfile = GetExactTime();
  154.     outputBuffer.clear();
  155.     outputBuffer += "  Ave :   Min :   Max :   # : Profile Name\n";
  156.     outputBuffer += "--------------------------------------------\n";
  157.     while (i < NUM_PROFILE_SAMPLES && g_samples[i].bValid == true) {
  158.         unsigned int indent = 0;
  159.         float sampleTime, percentTime;
  160.         char line[256], name[256];
  161.         std::string indentedName;
  162.         char ave[16], min[16], max[16], num[16];
  163.  
  164.         if (g_samples[i].iOpenProfiles < 0) { assert(!"ProfileEnd() called without a ProfileBegin()"); }
  165.         else if (g_samples[i].iOpenProfiles > 0) { assert(!"ProfileBegin() called without a ProfileEnd()"); }
  166.  
  167.         sampleTime = g_samples[i].fAccumulator - g_samples[i].fChildrenSampleTime;
  168.         percentTime = (sampleTime / (g_endProfile - g_startProfile)) * 100.0f;
  169.        
  170.  
  171.         //Add new measurement into the history and get the ave, min, and max
  172.         StoreProfileInHistory(g_samples[i].szName, percentTime);
  173.         auto [aveTime, minTime, maxTime] = GetProfileFromHistory(g_samples[i].szName);
  174.  
  175.         //TODO Format the data
  176.         /*std::stringstream output;
  177.         output << std::setprecision(4) <<;*/
  178.         sprintf_s(ave, "%3.1f", aveTime);
  179.         sprintf_s(min, "%3.1f", minTime);
  180.         sprintf_s(max, "%3.1f", maxTime);
  181.         sprintf_s(num, "%3d", g_samples[i].iProfileInstances);
  182.  
  183.         indentedName = g_samples[i].szName;
  184.         for (indent = 0; indent < g_samples[i].iNumParents; indent++) {
  185.             sprintf_s(name, "   %s", indentedName.c_str());
  186.             indentedName = name;
  187.         }
  188.         sprintf_s(line, "%3s : %3s : %3s : %3s : %s\n", ave, min, max, num, indentedName.c_str());
  189.         outputBuffer += line;   //Send the line to text buffer
  190.         i++;
  191.     }
  192.     {  //Reset samples for next frame
  193.         unsigned int j;
  194.         for (j = 0; j < NUM_PROFILE_SAMPLES; j++) {
  195.             g_samples[j].bValid = false;
  196.         }
  197.         g_startProfile = GetExactTime();
  198.     }
  199. }
  200.  
  201. void Profile::StoreProfileInHistory(const std::string& name, float percent) {
  202.     unsigned int i = 0;
  203.     float oldRatio;
  204.     float newRatio = 0.8f * GetElapsedTime();
  205.     if (newRatio > 1.0f) {
  206.         newRatio = 1.0f;
  207.     }
  208.     oldRatio = 1.0f - newRatio;
  209.     // TODO: replace with std::find
  210.     for (auto& sample : g_history) {
  211.         if (!sample.bValid) {
  212.             break;
  213.         }
  214.         if (sample.szName != name) {
  215.             i++;
  216.             continue;
  217.         }
  218.  
  219.         //Found the sample
  220.         sample.fAve = (sample.fAve*oldRatio) + (percent*newRatio);
  221.         if (percent > sample.fMax) {
  222.             sample.fMax = percent;
  223.         }
  224.         if (percent < sample.fMin) {
  225.             sample.fMin = percent;
  226.         }
  227.         else {
  228.             sample.fMin = (sample.fMin*oldRatio) + (percent*newRatio);
  229.         }
  230.         if (sample.fMin < 0.0f) {
  231.             sample.fMin = 0.0f;
  232.         }
  233.         else {
  234.             sample.fMax = (sample.fMax*oldRatio) + (percent*newRatio);
  235.         }
  236.         return;
  237.     }
  238.  
  239.     if (i < NUM_PROFILE_SAMPLES) {  //Add to history
  240.         g_history[i].szName = name;
  241.         g_history[i].bValid = true;
  242.         g_history[i].fAve = g_history[i].fMin = g_history[i].fMax = percent;
  243.     }
  244.     else {
  245.         assert(!"Exceeded Max Available Profile Samples!");
  246.     }
  247. }
  248.  
  249. Profile::SamplePoint Profile::GetProfileFromHistory(const std::string& name) {
  250.     SamplePoint result{};
  251.     for (auto& sample : g_history){
  252.         if (sample.bValid == true && sample.szName == name) {
  253.             result.ave = sample.fAve;
  254.             result.max = sample.fMax;
  255.             result.min = sample.fMin;
  256.  
  257.             return result;
  258.         }
  259.     }
  260.     return result;
  261. }
  262.  
  263. void Profile::Draw(void) {
  264.     std::cout << outputBuffer << '\n';
  265. }
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×