profiler.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. Minetest
  3. Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #ifndef PROFILER_HEADER
  17. #define PROFILER_HEADER
  18. #include "irrlichttypes.h"
  19. #include <string>
  20. #include <map>
  21. #include "jthread/jmutex.h"
  22. #include "jthread/jmutexautolock.h"
  23. #include "util/timetaker.h"
  24. #include "util/numeric.h" // paging()
  25. #include "debug.h" // assert()
  26. /*
  27. Time profiler
  28. */
  29. class Profiler
  30. {
  31. public:
  32. Profiler()
  33. {
  34. }
  35. void add(const std::string &name, float value)
  36. {
  37. JMutexAutoLock lock(m_mutex);
  38. {
  39. /* No average shall have been used; mark add used as -2 */
  40. std::map<std::string, int>::iterator n = m_avgcounts.find(name);
  41. if(n == m_avgcounts.end())
  42. m_avgcounts[name] = -2;
  43. else{
  44. if(n->second == -1)
  45. n->second = -2;
  46. assert(n->second == -2);
  47. }
  48. }
  49. {
  50. std::map<std::string, float>::iterator n = m_data.find(name);
  51. if(n == m_data.end())
  52. m_data[name] = value;
  53. else
  54. n->second += value;
  55. }
  56. }
  57. void avg(const std::string &name, float value)
  58. {
  59. JMutexAutoLock lock(m_mutex);
  60. {
  61. std::map<std::string, int>::iterator n = m_avgcounts.find(name);
  62. if(n == m_avgcounts.end())
  63. m_avgcounts[name] = 1;
  64. else{
  65. /* No add shall have been used */
  66. assert(n->second != -2);
  67. n->second = MYMAX(n->second, 0) + 1;
  68. }
  69. }
  70. {
  71. std::map<std::string, float>::iterator n = m_data.find(name);
  72. if(n == m_data.end())
  73. m_data[name] = value;
  74. else
  75. n->second += value;
  76. }
  77. }
  78. void clear()
  79. {
  80. JMutexAutoLock lock(m_mutex);
  81. for(std::map<std::string, float>::iterator
  82. i = m_data.begin();
  83. i != m_data.end(); ++i)
  84. {
  85. i->second = 0;
  86. }
  87. m_avgcounts.clear();
  88. }
  89. void print(std::ostream &o)
  90. {
  91. printPage(o, 1, 1);
  92. }
  93. void printPage(std::ostream &o, u32 page, u32 pagecount)
  94. {
  95. JMutexAutoLock lock(m_mutex);
  96. u32 minindex, maxindex;
  97. paging(m_data.size(), page, pagecount, minindex, maxindex);
  98. for(std::map<std::string, float>::iterator
  99. i = m_data.begin();
  100. i != m_data.end(); ++i)
  101. {
  102. if(maxindex == 0)
  103. break;
  104. maxindex--;
  105. if(minindex != 0)
  106. {
  107. minindex--;
  108. continue;
  109. }
  110. std::string name = i->first;
  111. int avgcount = 1;
  112. std::map<std::string, int>::iterator n = m_avgcounts.find(name);
  113. if(n != m_avgcounts.end()){
  114. if(n->second >= 1)
  115. avgcount = n->second;
  116. }
  117. o<<" "<<name<<": ";
  118. s32 clampsize = 40;
  119. s32 space = clampsize - name.size();
  120. for(s32 j=0; j<space; j++)
  121. {
  122. if(j%2 == 0 && j < space - 1)
  123. o<<"-";
  124. else
  125. o<<" ";
  126. }
  127. o<<(i->second / avgcount);
  128. o<<std::endl;
  129. }
  130. }
  131. typedef std::map<std::string, float> GraphValues;
  132. void graphAdd(const std::string &id, float value)
  133. {
  134. JMutexAutoLock lock(m_mutex);
  135. std::map<std::string, float>::iterator i =
  136. m_graphvalues.find(id);
  137. if(i == m_graphvalues.end())
  138. m_graphvalues[id] = value;
  139. else
  140. i->second += value;
  141. }
  142. void graphGet(GraphValues &result)
  143. {
  144. JMutexAutoLock lock(m_mutex);
  145. result = m_graphvalues;
  146. m_graphvalues.clear();
  147. }
  148. void remove(const std::string& name)
  149. {
  150. JMutexAutoLock lock(m_mutex);
  151. m_avgcounts.erase(name);
  152. m_data.erase(name);
  153. }
  154. private:
  155. JMutex m_mutex;
  156. std::map<std::string, float> m_data;
  157. std::map<std::string, int> m_avgcounts;
  158. std::map<std::string, float> m_graphvalues;
  159. };
  160. enum ScopeProfilerType{
  161. SPT_ADD,
  162. SPT_AVG,
  163. SPT_GRAPH_ADD
  164. };
  165. class ScopeProfiler
  166. {
  167. public:
  168. ScopeProfiler(Profiler *profiler, const std::string &name,
  169. enum ScopeProfilerType type = SPT_ADD):
  170. m_profiler(profiler),
  171. m_name(name),
  172. m_timer(NULL),
  173. m_type(type)
  174. {
  175. if(m_profiler)
  176. m_timer = new TimeTaker(m_name.c_str());
  177. }
  178. // name is copied
  179. ScopeProfiler(Profiler *profiler, const char *name,
  180. enum ScopeProfilerType type = SPT_ADD):
  181. m_profiler(profiler),
  182. m_name(name),
  183. m_timer(NULL),
  184. m_type(type)
  185. {
  186. if(m_profiler)
  187. m_timer = new TimeTaker(m_name.c_str());
  188. }
  189. ~ScopeProfiler()
  190. {
  191. if(m_timer)
  192. {
  193. float duration_ms = m_timer->stop(true);
  194. float duration = duration_ms / 1000.0;
  195. if(m_profiler){
  196. switch(m_type){
  197. case SPT_ADD:
  198. m_profiler->add(m_name, duration);
  199. break;
  200. case SPT_AVG:
  201. m_profiler->avg(m_name, duration);
  202. break;
  203. case SPT_GRAPH_ADD:
  204. m_profiler->graphAdd(m_name, duration);
  205. break;
  206. }
  207. }
  208. delete m_timer;
  209. }
  210. }
  211. private:
  212. Profiler *m_profiler;
  213. std::string m_name;
  214. TimeTaker *m_timer;
  215. enum ScopeProfilerType m_type;
  216. };
  217. #endif