wwprofile.cpp 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  1. /*
  2. ** Command & Conquer Renegade(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. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WWDebug *
  23. * *
  24. * $Archive:: /Commando/Code/wwdebug/wwprofile.cpp $*
  25. * *
  26. * $Author:: Jani_p $*
  27. * *
  28. * $Modtime:: 4/01/02 10:30a $*
  29. * *
  30. * $Revision:: 20 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * WWProfile_Get_Ticks -- Retrieves the cpu performance counter *
  34. * WWProfileHierachyNodeClass::WWProfileHierachyNodeClass -- Constructor *
  35. * WWProfileHierachyNodeClass::~WWProfileHierachyNodeClass -- Destructor *
  36. * WWProfileHierachyNodeClass::Get_Sub_Node -- Searches for a child node by name (pointer) *
  37. * WWProfileHierachyNodeClass::Reset -- Reset all profiling data in the tree *
  38. * WWProfileHierachyNodeClass::Call -- Start timing *
  39. * WWProfileHierachyNodeClass::Return -- Stop timing, record results *
  40. * WWProfileManager::Start_Profile -- Begin a named profile *
  41. * WWProfileManager::Stop_Profile -- Stop timing and record the results. *
  42. * WWProfileManager::Reset -- Reset the contents of the profiling system *
  43. * WWProfileManager::Increment_Frame_Counter -- Increment the frame counter *
  44. * WWProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset *
  45. * WWProfileManager::Get_Iterator -- Creates an iterator for the profile tree *
  46. * WWProfileManager::Release_Iterator -- Return an iterator for the profile tree *
  47. * WWProfileManager::Get_In_Order_Iterator -- Creates an "in-order" iterator for the profile *
  48. * WWProfileManager::Release_In_Order_Iterator -- Return an "in-order" iterator *
  49. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  50. #include "wwprofile.h"
  51. #include "fastallocator.h"
  52. #include "wwdebug.h"
  53. #include <windows.h>
  54. //#include "systimer.h"
  55. #include "systimer.h"
  56. #include "rawfile.h"
  57. #include "ffactory.h"
  58. #include "simplevec.h"
  59. #include "cpudetect.h"
  60. static SimpleDynVecClass<WWProfileHierachyNodeClass*> ProfileCollectVector;
  61. static double TotalFrameTimes;
  62. static bool ProfileCollecting;
  63. unsigned WWProfile_Get_System_Time()
  64. {
  65. return TIMEGETTIME();
  66. }
  67. /***********************************************************************************************
  68. * WWProfile_Get_Ticks -- Retrieves the cpu performance counter *
  69. * *
  70. * INPUT: *
  71. * *
  72. * OUTPUT: *
  73. * *
  74. * WARNINGS: *
  75. * *
  76. * HISTORY: *
  77. * 9/24/2000 gth : Created. *
  78. *=============================================================================================*/
  79. inline void WWProfile_Get_Ticks(_int64 * ticks)
  80. {
  81. #ifdef _UNIX
  82. *ticks = TIMEGETTIME();
  83. #else
  84. __asm
  85. {
  86. push edx;
  87. push ecx;
  88. push eax;
  89. mov ecx,ticks;
  90. _emit 0Fh
  91. _emit 31h
  92. mov [ecx],eax;
  93. mov [ecx+4],edx;
  94. pop eax;
  95. pop ecx;
  96. pop edx;
  97. }
  98. #endif
  99. }
  100. /***********************************************************************************************
  101. * WWProfileHierachyNodeClass::WWProfileHierachyNodeClass -- Constructor *
  102. * *
  103. * *
  104. * INPUT: *
  105. * name - pointer to a static string which is the name of this profile node *
  106. * parent - parent pointer *
  107. * *
  108. * OUTPUT: *
  109. * *
  110. * WARNINGS: *
  111. * The name is assumed to be a static pointer, only the pointer is stored and compared for *
  112. * efficiency reasons. *
  113. * *
  114. * HISTORY: *
  115. * 9/24/2000 gth : Created. *
  116. *=============================================================================================*/
  117. WWProfileHierachyNodeClass::WWProfileHierachyNodeClass( const char * name, WWProfileHierachyNodeClass * parent ) :
  118. Name( name ),
  119. TotalCalls( 0 ),
  120. TotalTime( 0 ),
  121. StartTime( 0 ),
  122. RecursionCounter( 0 ),
  123. Parent( parent ),
  124. Child( NULL ),
  125. Sibling( NULL )
  126. {
  127. Reset();
  128. }
  129. /***********************************************************************************************
  130. * WWProfileHierachyNodeClass::~WWProfileHierachyNodeClass -- Destructor *
  131. * *
  132. * INPUT: *
  133. * *
  134. * OUTPUT: *
  135. * *
  136. * WARNINGS: *
  137. * *
  138. * HISTORY: *
  139. * 9/24/2000 gth : Created. *
  140. *=============================================================================================*/
  141. WWProfileHierachyNodeClass::~WWProfileHierachyNodeClass( void )
  142. {
  143. delete Child;
  144. delete Sibling;
  145. }
  146. WWProfileHierachyNodeClass* WWProfileHierachyNodeClass::Clone_Hierarchy(WWProfileHierachyNodeClass* parent)
  147. {
  148. WWProfileHierachyNodeClass* node=new WWProfileHierachyNodeClass(Name,parent);
  149. node->TotalCalls=TotalCalls;
  150. node->TotalTime=TotalTime;
  151. node->StartTime=StartTime;
  152. node->RecursionCounter=RecursionCounter;
  153. if (Child) {
  154. node->Child=Child->Clone_Hierarchy(this);
  155. }
  156. if (Sibling) {
  157. node->Sibling=Sibling->Clone_Hierarchy(parent);
  158. }
  159. return node;
  160. }
  161. void WWProfileHierachyNodeClass::Write_To_File(FileClass* file,int recursion)
  162. {
  163. if (TotalTime!=0.0f) {
  164. int i;
  165. StringClass string;
  166. StringClass work;
  167. for (i=0;i<recursion;++i) { string+="\t"; }
  168. work.Format("%s\t%d\t%f\r\n",Name,TotalCalls,TotalTime*1000.0f);
  169. string+=work;
  170. file->Write(string.Peek_Buffer(),string.Get_Length());
  171. }
  172. if (Child) {
  173. Child->Write_To_File(file,recursion+1);
  174. }
  175. if (Sibling) {
  176. Sibling->Write_To_File(file,recursion);
  177. }
  178. }
  179. /***********************************************************************************************
  180. * WWProfileHierachyNodeClass::Get_Sub_Node -- Searches for a child node by name (pointer) *
  181. * *
  182. * INPUT: *
  183. * name - static string pointer to the name of the node we are searching for *
  184. * *
  185. * OUTPUT: *
  186. * *
  187. * WARNINGS: *
  188. * All profile names are assumed to be static strings so this function uses pointer compares *
  189. * to find the named node. *
  190. * *
  191. * HISTORY: *
  192. * 9/24/2000 gth : Created. *
  193. *=============================================================================================*/
  194. WWProfileHierachyNodeClass * WWProfileHierachyNodeClass::Get_Sub_Node( const char * name )
  195. {
  196. // Try to find this sub node
  197. WWProfileHierachyNodeClass * child = Child;
  198. while ( child ) {
  199. if ( child->Name == name ) {
  200. return child;
  201. }
  202. child = child->Sibling;
  203. }
  204. // We didn't find it, so add it
  205. WWProfileHierachyNodeClass * node = new WWProfileHierachyNodeClass( name, this );
  206. node->Sibling = Child;
  207. Child = node;
  208. return node;
  209. }
  210. /***********************************************************************************************
  211. * WWProfileHierachyNodeClass::Reset -- Reset all profiling data in the tree *
  212. * *
  213. * INPUT: *
  214. * *
  215. * OUTPUT: *
  216. * *
  217. * WARNINGS: *
  218. * *
  219. * HISTORY: *
  220. * 9/24/2000 gth : Created. *
  221. *=============================================================================================*/
  222. void WWProfileHierachyNodeClass::Reset( void )
  223. {
  224. TotalCalls = 0;
  225. TotalTime = 0.0f;
  226. if ( Child ) {
  227. Child->Reset();
  228. }
  229. if ( Sibling ) {
  230. Sibling->Reset();
  231. }
  232. }
  233. /***********************************************************************************************
  234. * WWProfileHierachyNodeClass::Call -- Start timing *
  235. * *
  236. * INPUT: *
  237. * *
  238. * OUTPUT: *
  239. * *
  240. * WARNINGS: *
  241. * *
  242. * HISTORY: *
  243. * 9/24/2000 gth : Created. *
  244. *=============================================================================================*/
  245. void WWProfileHierachyNodeClass::Call( void )
  246. {
  247. TotalCalls++;
  248. if (RecursionCounter++ == 0) {
  249. WWProfile_Get_Ticks(&StartTime);
  250. }
  251. }
  252. /***********************************************************************************************
  253. * WWProfileHierachyNodeClass::Return -- Stop timing, record results *
  254. * *
  255. * INPUT: *
  256. * *
  257. * OUTPUT: *
  258. * *
  259. * WARNINGS: *
  260. * *
  261. * HISTORY: *
  262. * 9/24/2000 gth : Created. *
  263. *=============================================================================================*/
  264. bool WWProfileHierachyNodeClass::Return( void )
  265. {
  266. if (--RecursionCounter == 0) {
  267. if ( TotalCalls != 0 ) {
  268. __int64 time;
  269. WWProfile_Get_Ticks(&time);
  270. time-=StartTime;
  271. TotalTime += float(double(time)*CPUDetectClass::Get_Inv_Processor_Ticks_Per_Second());
  272. }
  273. }
  274. return RecursionCounter == 0;
  275. }
  276. /***************************************************************************************************
  277. **
  278. ** WWProfileManager Implementation
  279. **
  280. ***************************************************************************************************/
  281. WWProfileHierachyNodeClass WWProfileManager::Root( "Root", NULL );
  282. WWProfileHierachyNodeClass * WWProfileManager::CurrentNode = &WWProfileManager::Root;
  283. WWProfileHierachyNodeClass * WWProfileManager::CurrentRootNode = &WWProfileManager::Root;
  284. int WWProfileManager::FrameCounter = 0;
  285. __int64 WWProfileManager::ResetTime = 0;
  286. static unsigned int ThreadID = static_cast<unsigned int>(-1);
  287. /***********************************************************************************************
  288. * WWProfileManager::Start_Profile -- Begin a named profile *
  289. * *
  290. * Steps one level deeper into the tree, if a child already exists with the specified name *
  291. * then it accumulates the profiling; otherwise a new child node is added to the profile tree. *
  292. * *
  293. * INPUT: *
  294. * name - name of this profiling record *
  295. * *
  296. * OUTPUT: *
  297. * *
  298. * WARNINGS: *
  299. * The string used is assumed to be a static string; pointer compares are used throughout *
  300. * the profiling code for efficiency. *
  301. * *
  302. * HISTORY: *
  303. * 9/24/2000 gth : Created. *
  304. *=============================================================================================*/
  305. void WWProfileManager::Start_Profile( const char * name )
  306. {
  307. if (::GetCurrentThreadId() != ThreadID) {
  308. return;
  309. }
  310. // int current_thread = ::GetCurrentThreadId();
  311. if (name != CurrentNode->Get_Name()) {
  312. CurrentNode = CurrentNode->Get_Sub_Node( name );
  313. }
  314. CurrentNode->Call();
  315. }
  316. void WWProfileManager::Start_Root_Profile( const char * name )
  317. {
  318. if (::GetCurrentThreadId() != ThreadID) {
  319. return;
  320. }
  321. if (name != CurrentRootNode->Get_Name()) {
  322. CurrentRootNode = CurrentRootNode->Get_Sub_Node( name );
  323. }
  324. CurrentRootNode->Call();
  325. }
  326. /***********************************************************************************************
  327. * WWProfileManager::Stop_Profile -- Stop timing and record the results. *
  328. * *
  329. * INPUT: *
  330. * *
  331. * OUTPUT: *
  332. * *
  333. * WARNINGS: *
  334. * *
  335. * HISTORY: *
  336. * 9/24/2000 gth : Created. *
  337. *=============================================================================================*/
  338. void WWProfileManager::Stop_Profile( void )
  339. {
  340. if (::GetCurrentThreadId() != ThreadID) {
  341. return;
  342. }
  343. // Return will indicate whether we should back up to our parent (we may
  344. // be profiling a recursive function)
  345. if (CurrentNode->Return()) {
  346. CurrentNode = CurrentNode->Get_Parent();
  347. }
  348. }
  349. void WWProfileManager::Stop_Root_Profile( void )
  350. {
  351. if (::GetCurrentThreadId() != ThreadID) {
  352. return;
  353. }
  354. // Return will indicate whether we should back up to our parent (we may
  355. // be profiling a recursive function)
  356. if (CurrentRootNode->Return()) {
  357. CurrentRootNode = CurrentRootNode->Get_Parent();
  358. }
  359. }
  360. /***********************************************************************************************
  361. * WWProfileManager::Reset -- Reset the contents of the profiling system *
  362. * *
  363. * This resets everything except for the tree structure. All of the timing data is reset. *
  364. * *
  365. * *
  366. * INPUT: *
  367. * *
  368. * OUTPUT: *
  369. * *
  370. * WARNINGS: *
  371. * *
  372. * HISTORY: *
  373. * 9/24/2000 gth : Created. *
  374. *=============================================================================================*/
  375. void WWProfileManager::Reset( void )
  376. {
  377. ThreadID = ::GetCurrentThreadId();
  378. Root.Reset();
  379. FrameCounter = 0;
  380. WWProfile_Get_Ticks(&ResetTime);
  381. }
  382. /***********************************************************************************************
  383. * WWProfileManager::Increment_Frame_Counter -- Increment the frame counter *
  384. * *
  385. * INPUT: *
  386. * *
  387. * OUTPUT: *
  388. * *
  389. * WARNINGS: *
  390. * *
  391. * HISTORY: *
  392. * 9/24/2000 gth : Created. *
  393. *=============================================================================================*/
  394. void WWProfileManager::Increment_Frame_Counter( void )
  395. {
  396. if (ProfileCollecting) {
  397. float time=Get_Time_Since_Reset();
  398. TotalFrameTimes+=time;
  399. WWProfileHierachyNodeClass* new_root=Root.Clone_Hierarchy(NULL);
  400. new_root->Set_Total_Time(time);
  401. new_root->Set_Total_Calls(1);
  402. ProfileCollectVector.Add(new_root);
  403. Reset();
  404. }
  405. FrameCounter++;
  406. }
  407. /***********************************************************************************************
  408. * WWProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset *
  409. * *
  410. * INPUT: *
  411. * *
  412. * OUTPUT: *
  413. * *
  414. * WARNINGS: *
  415. * *
  416. * HISTORY: *
  417. * 9/24/2000 gth : Created. *
  418. *=============================================================================================*/
  419. float WWProfileManager::Get_Time_Since_Reset( void )
  420. {
  421. __int64 time;
  422. WWProfile_Get_Ticks(&time);
  423. time -= ResetTime;
  424. return float(double(time) * CPUDetectClass::Get_Inv_Processor_Ticks_Per_Second());
  425. }
  426. /***********************************************************************************************
  427. * WWProfileManager::Get_Iterator -- Creates an iterator for the profile tree *
  428. * *
  429. * INPUT: *
  430. * *
  431. * OUTPUT: *
  432. * *
  433. * WARNINGS: *
  434. * *
  435. * HISTORY: *
  436. * 9/24/2000 gth : Created. *
  437. *=============================================================================================*/
  438. WWProfileIterator * WWProfileManager::Get_Iterator( void )
  439. {
  440. return new WWProfileIterator( &Root );
  441. }
  442. /***********************************************************************************************
  443. * WWProfileManager::Release_Iterator -- Return an iterator for the profile tree *
  444. * *
  445. * INPUT: *
  446. * *
  447. * OUTPUT: *
  448. * *
  449. * WARNINGS: *
  450. * *
  451. * HISTORY: *
  452. * 9/24/2000 gth : Created. *
  453. *=============================================================================================*/
  454. void WWProfileManager::Release_Iterator( WWProfileIterator * iterator )
  455. {
  456. delete iterator;
  457. }
  458. void WWProfileManager::Begin_Collecting()
  459. {
  460. Reset();
  461. ProfileCollecting=true;
  462. TotalFrameTimes=0.0;
  463. }
  464. void WWProfileManager::End_Collecting(const char* filename)
  465. {
  466. int i;
  467. if (filename && ProfileCollectVector.Count()!=0) {
  468. FileClass * file= _TheWritingFileFactory->Get_File(filename);
  469. if (file != NULL) {
  470. //
  471. // Open or create the file
  472. //
  473. file->Open (FileClass::WRITE);
  474. StringClass str;
  475. float avg_frame_time=TotalFrameTimes/float(ProfileCollectVector.Count());
  476. str.Format(
  477. "Total frames: %d, average frame time: %fms\r\n"
  478. "All frames taking more than twice the average frame time are marked with keyword SPIKE.\r\n\r\n",
  479. ProfileCollectVector.Count(),avg_frame_time*1000.0f);
  480. file->Write(str.Peek_Buffer(),str.Get_Length());
  481. for (i=0;i<ProfileCollectVector.Count();++i) {
  482. float frame_time=ProfileCollectVector[i]->Get_Total_Time();
  483. str.Format("FRAME: %d %fms %s ---------------\r\n",i,frame_time*1000.0f,frame_time>avg_frame_time*2.0f ? "SPIKE" : "");
  484. file->Write(str.Peek_Buffer(),str.Get_Length());
  485. ProfileCollectVector[i]->Write_To_File(file,0);
  486. }
  487. //
  488. // Close the file
  489. //
  490. file->Close ();
  491. _TheWritingFileFactory->Return_File (file);
  492. }
  493. }
  494. for (i=0;i<ProfileCollectVector.Count();++i) {
  495. delete ProfileCollectVector[i];
  496. ProfileCollectVector[i]=0;
  497. }
  498. ProfileCollectVector.Delete_All();
  499. ProfileCollecting=false;
  500. }
  501. /***********************************************************************************************
  502. * WWProfileManager::Get_In_Order_Iterator -- Creates an "in-order" iterator for the profile t *
  503. * *
  504. * INPUT: *
  505. * *
  506. * OUTPUT: *
  507. * *
  508. * WARNINGS: *
  509. * *
  510. * HISTORY: *
  511. * 9/24/2000 gth : Created. *
  512. *=============================================================================================*/
  513. WWProfileInOrderIterator * WWProfileManager::Get_In_Order_Iterator( void )
  514. {
  515. return new WWProfileInOrderIterator;
  516. }
  517. /***********************************************************************************************
  518. * WWProfileManager::Release_In_Order_Iterator -- Return an "in-order" iterator *
  519. * *
  520. * INPUT: *
  521. * *
  522. * OUTPUT: *
  523. * *
  524. * WARNINGS: *
  525. * *
  526. * HISTORY: *
  527. * 9/24/2000 gth : Created. *
  528. *=============================================================================================*/
  529. void WWProfileManager::Release_In_Order_Iterator( WWProfileInOrderIterator * iterator )
  530. {
  531. delete iterator;
  532. }
  533. /***************************************************************************************************
  534. **
  535. ** WWProfileIterator Implementation
  536. **
  537. ***************************************************************************************************/
  538. WWProfileIterator::WWProfileIterator( WWProfileHierachyNodeClass * start )
  539. {
  540. CurrentParent = start;
  541. CurrentChild = CurrentParent->Get_Child();
  542. }
  543. void WWProfileIterator::First(void)
  544. {
  545. CurrentChild = CurrentParent->Get_Child();
  546. }
  547. void WWProfileIterator::Next(void)
  548. {
  549. CurrentChild = CurrentChild->Get_Sibling();
  550. }
  551. bool WWProfileIterator::Is_Done(void)
  552. {
  553. return CurrentChild == NULL;
  554. }
  555. void WWProfileIterator::Enter_Child( void )
  556. {
  557. CurrentParent = CurrentChild;
  558. CurrentChild = CurrentParent->Get_Child();
  559. }
  560. void WWProfileIterator::Enter_Child( int index )
  561. {
  562. CurrentChild = CurrentParent->Get_Child();
  563. while ( (CurrentChild != NULL) && (index != 0) ) {
  564. index--;
  565. CurrentChild = CurrentChild->Get_Sibling();
  566. }
  567. if ( CurrentChild != NULL ) {
  568. CurrentParent = CurrentChild;
  569. CurrentChild = CurrentParent->Get_Child();
  570. }
  571. }
  572. void WWProfileIterator::Enter_Parent( void )
  573. {
  574. if ( CurrentParent->Get_Parent() != NULL ) {
  575. CurrentParent = CurrentParent->Get_Parent();
  576. }
  577. CurrentChild = CurrentParent->Get_Child();
  578. }
  579. /***************************************************************************************************
  580. **
  581. ** WWProfileInOrderIterator Implementation
  582. **
  583. ***************************************************************************************************/
  584. WWProfileInOrderIterator::WWProfileInOrderIterator( void )
  585. {
  586. CurrentNode = &WWProfileManager::Root;
  587. }
  588. void WWProfileInOrderIterator::First(void)
  589. {
  590. CurrentNode = &WWProfileManager::Root;
  591. }
  592. void WWProfileInOrderIterator::Next(void)
  593. {
  594. if ( CurrentNode->Get_Child() ) { // If I have a child, go to child
  595. CurrentNode = CurrentNode->Get_Child();
  596. } else if ( CurrentNode->Get_Sibling() ) { // If I have a sibling, go to sibling
  597. CurrentNode = CurrentNode->Get_Sibling();
  598. } else { // if not, go to my parent's sibling, or his.......
  599. // Find a parent with a sibling....
  600. bool done = false;
  601. while ( CurrentNode != NULL && !done ) {
  602. // go to my parent
  603. CurrentNode = CurrentNode->Get_Parent();
  604. // If I have a sibling, go there
  605. if ( CurrentNode != NULL && CurrentNode->Get_Sibling() != NULL ) {
  606. CurrentNode = CurrentNode->Get_Sibling();
  607. done = true;
  608. }
  609. }
  610. }
  611. }
  612. bool WWProfileInOrderIterator::Is_Done(void)
  613. {
  614. return CurrentNode == NULL;
  615. }
  616. /*
  617. **
  618. */
  619. WWTimeItClass::WWTimeItClass( const char * name )
  620. {
  621. Name = name;
  622. WWProfile_Get_Ticks( &Time );
  623. }
  624. WWTimeItClass::~WWTimeItClass( void )
  625. {
  626. __int64 End;
  627. WWProfile_Get_Ticks( &End );
  628. End -= Time;
  629. #ifdef WWDEBUG
  630. float time = End * CPUDetectClass::Get_Inv_Processor_Ticks_Per_Second();
  631. WWDEBUG_SAY(( "*** WWTIMEIT *** %s took %1.9f\n", Name, time ));
  632. #endif
  633. }
  634. /*
  635. **
  636. */
  637. WWMeasureItClass::WWMeasureItClass( float * p_result )
  638. {
  639. WWASSERT(p_result != NULL);
  640. PResult = p_result;
  641. WWProfile_Get_Ticks( &Time );
  642. }
  643. WWMeasureItClass::~WWMeasureItClass( void )
  644. {
  645. __int64 End;
  646. WWProfile_Get_Ticks( &End );
  647. End -= Time;
  648. WWASSERT(PResult != NULL);
  649. *PResult = End * CPUDetectClass::Get_Inv_Processor_Ticks_Per_Second();
  650. }
  651. // ----------------------------------------------------------------------------
  652. //
  653. //
  654. //
  655. // ----------------------------------------------------------------------------
  656. unsigned WWMemoryAndTimeLog::TabCount;
  657. WWMemoryAndTimeLog::WWMemoryAndTimeLog(const char* name)
  658. :
  659. Name(name),
  660. TimeStart(WWProfile_Get_System_Time()),
  661. AllocCountStart(FastAllocatorGeneral::Get_Allocator()->Get_Total_Allocation_Count()),
  662. AllocSizeStart(FastAllocatorGeneral::Get_Allocator()->Get_Total_Allocated_Size())
  663. {
  664. IntermediateTimeStart=TimeStart;
  665. IntermediateAllocCountStart=AllocCountStart;
  666. IntermediateAllocSizeStart=AllocSizeStart;
  667. StringClass tmp(0,true);
  668. for (unsigned i=0;i<TabCount;++i) tmp+="\t";
  669. WWRELEASE_SAY(("%s%s {\n",tmp,name));
  670. TabCount++;
  671. }
  672. WWMemoryAndTimeLog::~WWMemoryAndTimeLog()
  673. {
  674. if (TabCount>0) TabCount--;
  675. StringClass tmp(0,true);
  676. for (unsigned i=0;i<TabCount;++i) tmp+="\t";
  677. WWRELEASE_SAY(("%s} ",tmp));
  678. unsigned current_time=WWProfile_Get_System_Time();
  679. int current_alloc_count=FastAllocatorGeneral::Get_Allocator()->Get_Total_Allocation_Count();
  680. int current_alloc_size=FastAllocatorGeneral::Get_Allocator()->Get_Total_Allocated_Size();
  681. WWRELEASE_SAY(("IN TOTAL %s took %d.%3.3d s, did %d memory allocations of %d bytes\n",
  682. Name,
  683. (current_time - TimeStart)/1000, (current_time - TimeStart)%1000,
  684. current_alloc_count - AllocCountStart,
  685. current_alloc_size - AllocSizeStart));
  686. WWRELEASE_SAY(("\n"));
  687. }
  688. void WWMemoryAndTimeLog::Log_Intermediate(const char* text)
  689. {
  690. unsigned current_time=WWProfile_Get_System_Time();
  691. int current_alloc_count=FastAllocatorGeneral::Get_Allocator()->Get_Total_Allocation_Count();
  692. int current_alloc_size=FastAllocatorGeneral::Get_Allocator()->Get_Total_Allocated_Size();
  693. StringClass tmp(0,true);
  694. for (unsigned i=0;i<TabCount;++i) tmp+="\t";
  695. WWRELEASE_SAY(("%s%s took %d.%3.3d s, did %d memory allocations of %d bytes\n",
  696. tmp,
  697. text,
  698. (current_time - IntermediateTimeStart)/1000, (current_time - IntermediateTimeStart)%1000,
  699. current_alloc_count - IntermediateAllocCountStart,
  700. current_alloc_size - IntermediateAllocSizeStart));
  701. IntermediateTimeStart=current_time;
  702. IntermediateAllocCountStart=current_alloc_count;
  703. IntermediateAllocSizeStart=current_alloc_size;
  704. }