profile_highlevel.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /////////////////////////////////////////////////////////////////////////EA-V1
  19. // $File: //depot/GeneralsMD/Staging/code/Libraries/Source/profile/profile_highlevel.cpp $
  20. // $Author: mhoffe $
  21. // $Revision: #2 $
  22. // $DateTime: 2003/08/14 13:43:29 $
  23. //
  24. // ©2003 Electronic Arts
  25. //
  26. // High level profiling
  27. //////////////////////////////////////////////////////////////////////////////
  28. #include "_pch.h"
  29. #include <new>
  30. #include <stdio.h>
  31. // our own fast critical section
  32. static ProfileFastCS cs;
  33. //////////////////////////////////////////////////////////////////////////////
  34. // ProfileHighLevel::Id
  35. void ProfileHighLevel::Id::Increment(double add)
  36. {
  37. if (m_idPtr)
  38. m_idPtr->Increment(add);
  39. }
  40. void ProfileHighLevel::Id::SetMax(double max)
  41. {
  42. if (m_idPtr)
  43. m_idPtr->Maximum(max);
  44. }
  45. const char *ProfileHighLevel::Id::GetName(void) const
  46. {
  47. return m_idPtr?m_idPtr->GetName():NULL;
  48. }
  49. const char *ProfileHighLevel::Id::GetDescr(void) const
  50. {
  51. return m_idPtr?m_idPtr->GetDescr():NULL;
  52. }
  53. const char *ProfileHighLevel::Id::GetUnit(void) const
  54. {
  55. return m_idPtr?m_idPtr->GetUnit():NULL;
  56. }
  57. const char *ProfileHighLevel::Id::GetCurrentValue(void) const
  58. {
  59. return m_idPtr?m_idPtr->AsString(m_idPtr->GetCurrentValue()):NULL;
  60. }
  61. const char *ProfileHighLevel::Id::GetValue(unsigned frame) const
  62. {
  63. double v;
  64. if (!m_idPtr||!m_idPtr->GetFrameValue(frame,v))
  65. return NULL;
  66. return m_idPtr->AsString(v);
  67. }
  68. const char *ProfileHighLevel::Id::GetTotalValue(void) const
  69. {
  70. return m_idPtr?m_idPtr->AsString(m_idPtr->GetTotalValue()):NULL;
  71. }
  72. //////////////////////////////////////////////////////////////////////////////
  73. // ProfileHighLevel::Block
  74. ProfileHighLevel::Block::Block(const char *name)
  75. {
  76. DFAIL_IF(!name) return;
  77. m_idTime=AddProfile(name,NULL,"msec",6,-4);
  78. char help[256];
  79. strncpy(help,name,sizeof(help));
  80. help[sizeof(help)-1-2]=0;
  81. strcat(help,".c");
  82. AddProfile(help,NULL,"calls",6,0).Increment();
  83. ProfileGetTime(m_start);
  84. }
  85. ProfileHighLevel::Block::~Block()
  86. {
  87. _int64 end;
  88. ProfileGetTime(end);
  89. end-=m_start;
  90. m_idTime.Increment(double(end)/(double)Profile::GetClockCyclesPerSecond());
  91. }
  92. //////////////////////////////////////////////////////////////////////////////
  93. // ProfileId
  94. // profile ID stuff
  95. ProfileId *ProfileId::first;
  96. int ProfileId::curFrame;
  97. unsigned ProfileId::frameRecordMask;
  98. char ProfileId::stringBuf[ProfileId::STRING_BUFFER_SIZE];
  99. unsigned ProfileId::stringBufUnused;
  100. ProfileId::ProfileId(const char *name, const char *descr, const char *unit, int precision, int exp10)
  101. {
  102. m_next=first; first=this;
  103. m_name=(char *)ProfileAllocMemory(strlen(name)+1);
  104. strcpy(m_name,name);
  105. if (descr)
  106. {
  107. m_descr=(char *)ProfileAllocMemory(strlen(descr)+1);
  108. strcpy(m_descr,descr);
  109. }
  110. else
  111. m_descr=NULL;
  112. if (unit)
  113. {
  114. m_unit=(char *)ProfileAllocMemory(strlen(unit)+1);
  115. strcpy(m_unit,unit);
  116. }
  117. else
  118. m_unit=NULL;
  119. m_precision=precision;
  120. m_exp10=exp10;
  121. m_curVal=m_totalVal=0.;
  122. m_recFrameVal=NULL;
  123. m_firstFrame=curFrame;
  124. m_valueMode=Unknown;
  125. }
  126. void ProfileId::Increment(double add)
  127. {
  128. DFAIL_IF(m_valueMode!=Unknown&&m_valueMode!=ModeIncrement)
  129. return;
  130. m_valueMode=ModeIncrement;
  131. m_curVal+=add;
  132. m_totalVal+=add;
  133. if (frameRecordMask)
  134. {
  135. unsigned mask=frameRecordMask;
  136. for (unsigned i=0;i<MAX_FRAME_RECORDS;i++)
  137. {
  138. if (mask&1)
  139. m_frameVal[i]+=add;
  140. if (!(mask>>=1))
  141. break;
  142. }
  143. }
  144. }
  145. void ProfileId::Maximum(double max)
  146. {
  147. DFAIL_IF(m_valueMode!=Unknown&&m_valueMode!=ModeMaximum)
  148. return;
  149. m_valueMode=ModeMaximum;
  150. if (max>m_curVal)
  151. m_curVal=max;
  152. if (max>m_totalVal)
  153. m_totalVal=max;
  154. if (frameRecordMask)
  155. {
  156. unsigned mask=frameRecordMask;
  157. for (unsigned i=0;i<MAX_FRAME_RECORDS;i++)
  158. {
  159. if (mask&1)
  160. {
  161. if (max>m_frameVal[i])
  162. m_frameVal[i]=max;
  163. }
  164. if (!(mask>>=1))
  165. break;
  166. }
  167. }
  168. }
  169. const char *ProfileId::AsString(double v) const
  170. {
  171. char help1[10],help[40];
  172. wsprintf(help1,"%%%i.lf",m_precision);
  173. double mul=1.0;
  174. int k;
  175. for (k=m_exp10;k<0;k++) mul*=10.0;
  176. for (;k>0;k--) mul/=10.0;
  177. unsigned len=_snprintf(help,sizeof(help),help1,v*mul)+1;
  178. ProfileFastCS::Lock lock(cs);
  179. if (stringBufUnused+len>STRING_BUFFER_SIZE)
  180. stringBufUnused=0;
  181. char *ret=stringBuf+stringBufUnused;
  182. memcpy(ret,help,len);
  183. stringBufUnused+=len;
  184. return ret;
  185. }
  186. int ProfileId::FrameStart(void)
  187. {
  188. ProfileFastCS::Lock lock(cs);
  189. for (unsigned i=0;i<MAX_FRAME_RECORDS;i++)
  190. if (!(frameRecordMask&(1<<i)))
  191. break;
  192. if (i==MAX_FRAME_RECORDS)
  193. return -1;
  194. for (ProfileId *p=first;p;p=p->m_next)
  195. p->m_frameVal[i]=0.;
  196. frameRecordMask|=1<<i;
  197. return i;
  198. }
  199. void ProfileId::FrameEnd(int which, int mixIndex)
  200. {
  201. DFAIL_IF(which<0||which>=MAX_FRAME_RECORDS)
  202. return;
  203. DFAIL_IF(!(frameRecordMask&(1<<which)))
  204. return;
  205. DFAIL_IF(mixIndex>=curFrame)
  206. return;
  207. ProfileFastCS::Lock lock(cs);
  208. frameRecordMask^=1<<which;
  209. if (mixIndex<0)
  210. {
  211. // new frame
  212. curFrame++;
  213. for (ProfileId *p=first;p;p=p->m_next)
  214. {
  215. p->m_recFrameVal=(double *)ProfileReAllocMemory(p->m_recFrameVal,sizeof(double)*(curFrame-p->m_firstFrame));
  216. p->m_recFrameVal[curFrame-p->m_firstFrame-1]=p->m_frameVal[which];
  217. }
  218. }
  219. else
  220. {
  221. // append data
  222. for (ProfileId *p=first;p;p=p->m_next)
  223. {
  224. if (p->m_firstFrame>mixIndex)
  225. continue;
  226. double &val=p->m_recFrameVal[mixIndex-p->m_firstFrame];
  227. switch(p->m_valueMode)
  228. {
  229. case ProfileId::Unknown:
  230. break;
  231. case ProfileId::ModeIncrement:
  232. val+=p->m_frameVal[which];
  233. break;
  234. case ProfileId::ModeMaximum:
  235. if (p->m_frameVal[which]>val)
  236. val=p->m_frameVal[which];
  237. break;
  238. default:
  239. DFAIL();
  240. }
  241. }
  242. }
  243. }
  244. void ProfileId::Shutdown(void)
  245. {
  246. if (frameRecordMask)
  247. {
  248. for (unsigned i=0;i<MAX_FRAME_RECORDS;i++)
  249. if (frameRecordMask&(1<<i))
  250. FrameEnd(i,-1);
  251. }
  252. }
  253. //////////////////////////////////////////////////////////////////////////////
  254. // ProfileHighLevel
  255. ProfileHighLevel::Id ProfileHighLevel::AddProfile(const char *name, const char *descr, const char *unit, int precision, int exp10)
  256. {
  257. // check if there is already an ID with the given name...
  258. Id id;
  259. if (FindProfile(name,id))
  260. return id;
  261. // checks...
  262. DFAIL_IF(!name) return id;
  263. // no, allocate one
  264. ProfileFastCS::Lock lock(cs);
  265. id.m_idPtr=new (ProfileAllocMemory(sizeof(ProfileId))) ProfileId(name,descr,unit,precision,exp10);
  266. return id;
  267. }
  268. bool ProfileHighLevel::EnumProfile(unsigned index, Id &id)
  269. {
  270. ProfileFastCS::Lock lock(cs);
  271. for (ProfileId *cur=ProfileId::GetFirst();cur&&index--;cur=cur->GetNext());
  272. id.m_idPtr=cur;
  273. return cur!=NULL;
  274. }
  275. bool ProfileHighLevel::FindProfile(const char *name, Id &id)
  276. {
  277. DFAIL_IF(!name) return false;
  278. ProfileFastCS::Lock lock(cs);
  279. for (ProfileId *cur=ProfileId::GetFirst();cur;cur=cur->GetNext())
  280. if (!strcmp(name,cur->GetName()))
  281. {
  282. id.m_idPtr=cur;
  283. return true;
  284. }
  285. id.m_idPtr=NULL;
  286. return false;
  287. }
  288. ProfileHighLevel::ProfileHighLevel(void)
  289. {
  290. }
  291. ProfileHighLevel ProfileHighLevel::Instance;