Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
wwprofile.cpp
Go to the documentation of this file.
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
19/***********************************************************************************************
20 *** 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 ***
21 ***********************************************************************************************
22 * *
23 * Project Name : WWDebug *
24 * *
25 * $Archive:: /Commando/Code/wwdebug/wwprofile.cpp $*
26 * *
27 * $Author:: Jani_p $*
28 * *
29 * $Modtime:: 4/01/02 10:30a $*
30 * *
31 * $Revision:: 20 $*
32 * *
33 *---------------------------------------------------------------------------------------------*
34 * WWProfile_Get_Ticks -- Retrieves the cpu performance counter *
35 * WWProfileHierachyNodeClass::WWProfileHierachyNodeClass -- Constructor *
36 * WWProfileHierachyNodeClass::~WWProfileHierachyNodeClass -- Destructor *
37 * WWProfileHierachyNodeClass::Get_Sub_Node -- Searches for a child node by name (pointer) *
38 * WWProfileHierachyNodeClass::Reset -- Reset all profiling data in the tree *
39 * WWProfileHierachyNodeClass::Call -- Start timing *
40 * WWProfileHierachyNodeClass::Return -- Stop timing, record results *
41 * WWProfileManager::Start_Profile -- Begin a named profile *
42 * WWProfileManager::Stop_Profile -- Stop timing and record the results. *
43 * WWProfileManager::Reset -- Reset the contents of the profiling system *
44 * WWProfileManager::Increment_Frame_Counter -- Increment the frame counter *
45 * WWProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset *
46 * WWProfileManager::Get_Iterator -- Creates an iterator for the profile tree *
47 * WWProfileManager::Release_Iterator -- Return an iterator for the profile tree *
48 * WWProfileManager::Get_In_Order_Iterator -- Creates an "in-order" iterator for the profile *
49 * WWProfileManager::Release_In_Order_Iterator -- Return an "in-order" iterator *
50 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
51
52#include "always.h"
53#include "wwprofile.h"
54#include "fastallocator.h"
55#include "wwdebug.h"
56#include <windows.h>
57//#include "systimer.h"
58#include "systimer.h"
59#include "rawfile.h"
60#include "ffactory.h"
61#include "simplevec.h"
62#include "cpudetect.h"
63#include "hashtemplate.h"
64#include <stdio.h>
65
66static SimpleDynVecClass<WWProfileHierachyNodeClass*> ProfileCollectVector;
67static double TotalFrameTimes;
68static bool ProfileCollecting;
69
70static HashTemplateClass<StringClass, unsigned> ProfileStringHash;
71static unsigned ProfileStringCount;
72
74{
75 return TIMEGETTIME();
76}
77
79{
80#ifdef WIN32
82#elif defined (_UNIX)
83 return 0.001;
84#endif
85}
86
87/***********************************************************************************************
88 * WWProfile_Get_Ticks -- Retrieves the cpu performance counter *
89 * *
90 * INPUT: *
91 * *
92 * OUTPUT: *
93 * *
94 * WARNINGS: *
95 * *
96 * HISTORY: *
97 * 9/24/2000 gth : Created. *
98 *=============================================================================================*/
99inline void WWProfile_Get_Ticks(_int64 * ticks)
100{
101#ifdef _UNIX
102 *ticks = TIMEGETTIME();
103#else
104 __asm
105 {
106 push edx;
107 push ecx;
108 push eax;
109 mov ecx,ticks;
110 _emit 0Fh
111 _emit 31h
112 mov [ecx],eax;
113 mov [ecx+4],edx;
114 pop eax;
115 pop ecx;
116 pop edx;
117 }
118#endif
119}
120
121
122/***********************************************************************************************
123 * WWProfileHierachyNodeClass::WWProfileHierachyNodeClass -- Constructor *
124 * *
125 * *
126 * INPUT: *
127 * name - pointer to a static string which is the name of this profile node *
128 * parent - parent pointer *
129 * *
130 * OUTPUT: *
131 * *
132 * WARNINGS: *
133 * The name is assumed to be a static pointer, only the pointer is stored and compared for *
134 * efficiency reasons. *
135 * *
136 * HISTORY: *
137 * 9/24/2000 gth : Created. *
138 *=============================================================================================*/
140 Name( name ),
141 TotalCalls( 0 ),
142 TotalTime( 0 ),
143 StartTime( 0 ),
144 RecursionCounter( 0 ),
145 Parent( parent ),
146 Child( NULL ),
147 Sibling( NULL )
148{
149 Reset();
150
151 if (!ProfileStringHash.Get(name, ProfileStringID)) {
152 ProfileStringID=ProfileStringCount++;
153 ProfileStringHash.Insert(name,ProfileStringID);
154 }
155}
156
158 Name( NULL ),
159 TotalCalls( 0 ),
160 TotalTime( 0 ),
161 StartTime( 0 ),
162 RecursionCounter( 0 ),
163 Parent( parent ),
164 Child( NULL ),
165 Sibling( NULL ),
167{
168 Reset();
169}
170
171
172/***********************************************************************************************
173 * WWProfileHierachyNodeClass::~WWProfileHierachyNodeClass -- Destructor *
174 * *
175 * INPUT: *
176 * *
177 * OUTPUT: *
178 * *
179 * WARNINGS: *
180 * *
181 * HISTORY: *
182 * 9/24/2000 gth : Created. *
183 *=============================================================================================*/
189
190
192{
195 node->TotalTime=TotalTime;
196 node->StartTime=StartTime;
198
199 if (Child) {
200 node->Child=Child->Clone_Hierarchy(this);
201 }
202 if (Sibling) {
203 node->Sibling=Sibling->Clone_Hierarchy(parent);
204 }
205
206 return node;
207}
208
210{
211 if (TotalTime!=0.0f) {
212 int i;
213 StringClass string;
214 StringClass work;
215 for (i=0;i<recursion;++i) { string+="\t"; }
216 work.Format("%s\t%d\t%f\r\n",Name,TotalCalls,TotalTime*1000.0f);
217 string+=work;
218 file->Write(string.Peek_Buffer(),string.Get_Length());
219 }
220 if (Child) {
221 Child->Write_To_File(file,recursion+1);
222 }
223 if (Sibling) {
224 Sibling->Write_To_File(file,recursion);
225 }
226}
227
229{
230 if (TotalTime!=0.0f) {
231 StringClass work;
232 work.Format("%d %d %2.2f;",ProfileStringID,TotalCalls,TotalTime*1000.0f);
233 string+=work;
234 }
235 if (Child) {
236 StringClass work;
237 Child->Add_To_String_Compact(work,recursion+1);
238 if (work.Get_Length()!=0) {
239 string+="{";
240 string+=work;
241 string+="}";
242 }
243 }
244 if (Sibling) {
245 Sibling->Add_To_String_Compact(string,recursion);
246 }
247}
248
249/***********************************************************************************************
250 * WWProfileHierachyNodeClass::Get_Sub_Node -- Searches for a child node by name (pointer) *
251 * *
252 * INPUT: *
253 * name - static string pointer to the name of the node we are searching for *
254 * *
255 * OUTPUT: *
256 * *
257 * WARNINGS: *
258 * All profile names are assumed to be static strings so this function uses pointer compares *
259 * to find the named node. *
260 * *
261 * HISTORY: *
262 * 9/24/2000 gth : Created. *
263 *=============================================================================================*/
265{
266 // Try to find this sub node
268 while ( child ) {
269 if ( child->Name == name ) {
270 return child;
271 }
272 child = child->Sibling;
273 }
274
275 // We didn't find it, so add it
277 node->Sibling = Child;
278 Child = node;
279 return node;
280}
281
282
283/***********************************************************************************************
284 * WWProfileHierachyNodeClass::Reset -- Reset all profiling data in the tree *
285 * *
286 * INPUT: *
287 * *
288 * OUTPUT: *
289 * *
290 * WARNINGS: *
291 * *
292 * HISTORY: *
293 * 9/24/2000 gth : Created. *
294 *=============================================================================================*/
296{
297 TotalCalls = 0;
298 TotalTime = 0.0f;
299
300 if ( Child ) {
301 Child->Reset();
302 }
303 if ( Sibling ) {
304 Sibling->Reset();
305 }
306}
307
308
309/***********************************************************************************************
310 * WWProfileHierachyNodeClass::Call -- Start timing *
311 * *
312 * INPUT: *
313 * *
314 * OUTPUT: *
315 * *
316 * WARNINGS: *
317 * *
318 * HISTORY: *
319 * 9/24/2000 gth : Created. *
320 *=============================================================================================*/
322{
323 TotalCalls++;
324 if (RecursionCounter++ == 0) {
326 }
327}
328
329
330/***********************************************************************************************
331 * WWProfileHierachyNodeClass::Return -- Stop timing, record results *
332 * *
333 * INPUT: *
334 * *
335 * OUTPUT: *
336 * *
337 * WARNINGS: *
338 * *
339 * HISTORY: *
340 * 9/24/2000 gth : Created. *
341 *=============================================================================================*/
343{
344 if (--RecursionCounter == 0) {
345 if ( TotalCalls != 0 ) {
346 __int64 time;
347 WWProfile_Get_Ticks(&time);
348 time-=StartTime;
349
351 }
352 }
353 return RecursionCounter == 0;
354}
355
356
357/***************************************************************************************************
358**
359** WWProfileManager Implementation
360**
361***************************************************************************************************/
362bool WWProfileManager::IsProfileEnabled=false;
363WWProfileHierachyNodeClass WWProfileManager::Root( "Root", NULL );
364WWProfileHierachyNodeClass * WWProfileManager::CurrentNode = &WWProfileManager::Root;
365WWProfileHierachyNodeClass * WWProfileManager::CurrentRootNode = &WWProfileManager::Root;
366int WWProfileManager::FrameCounter = 0;
367__int64 WWProfileManager::ResetTime = 0;
368
369static unsigned int ThreadID = static_cast<unsigned int>(-1);
370
371
372/***********************************************************************************************
373 * WWProfileManager::Start_Profile -- Begin a named profile *
374 * *
375 * Steps one level deeper into the tree, if a child already exists with the specified name *
376 * then it accumulates the profiling; otherwise a new child node is added to the profile tree. *
377 * *
378 * INPUT: *
379 * name - name of this profiling record *
380 * *
381 * OUTPUT: *
382 * *
383 * WARNINGS: *
384 * The string used is assumed to be a static string; pointer compares are used throughout *
385 * the profiling code for efficiency. *
386 * *
387 * HISTORY: *
388 * 9/24/2000 gth : Created. *
389 *=============================================================================================*/
390void WWProfileManager::Start_Profile( const char * name )
391{
392 if (::GetCurrentThreadId() != ThreadID) {
393 return;
394 }
395
396// int current_thread = ::GetCurrentThreadId();
397 if (name != CurrentNode->Get_Name()) {
398 CurrentNode = CurrentNode->Get_Sub_Node( name );
399 }
400
401 CurrentNode->Call();
402}
403
405{
406 if (::GetCurrentThreadId() != ThreadID) {
407 return;
408 }
409
410 if (name != CurrentRootNode->Get_Name()) {
411 CurrentRootNode = CurrentRootNode->Get_Sub_Node( name );
412 }
413
414 CurrentRootNode->Call();
415}
416
417
418/***********************************************************************************************
419 * WWProfileManager::Stop_Profile -- Stop timing and record the results. *
420 * *
421 * INPUT: *
422 * *
423 * OUTPUT: *
424 * *
425 * WARNINGS: *
426 * *
427 * HISTORY: *
428 * 9/24/2000 gth : Created. *
429 *=============================================================================================*/
431{
432 if (::GetCurrentThreadId() != ThreadID) {
433 return;
434 }
435
436 // Return will indicate whether we should back up to our parent (we may
437 // be profiling a recursive function)
438 if (CurrentNode->Return()) {
439 CurrentNode = CurrentNode->Get_Parent();
440 }
441}
442
444{
445 if (::GetCurrentThreadId() != ThreadID) {
446 return;
447 }
448
449 // Return will indicate whether we should back up to our parent (we may
450 // be profiling a recursive function)
451 if (CurrentRootNode->Return()) {
452 CurrentRootNode = CurrentRootNode->Get_Parent();
453 }
454}
455
456
457/***********************************************************************************************
458 * WWProfileManager::Reset -- Reset the contents of the profiling system *
459 * *
460 * This resets everything except for the tree structure. All of the timing data is reset. *
461 * *
462 * *
463 * INPUT: *
464 * *
465 * OUTPUT: *
466 * *
467 * WARNINGS: *
468 * *
469 * HISTORY: *
470 * 9/24/2000 gth : Created. *
471 *=============================================================================================*/
473{
474 ThreadID = ::GetCurrentThreadId();
475
476 Root.Reset();
477 FrameCounter = 0;
478 WWProfile_Get_Ticks(&ResetTime);
479}
480
481
482/***********************************************************************************************
483 * WWProfileManager::Increment_Frame_Counter -- Increment the frame counter *
484 * *
485 * INPUT: *
486 * *
487 * OUTPUT: *
488 * *
489 * WARNINGS: *
490 * *
491 * HISTORY: *
492 * 9/24/2000 gth : Created. *
493 *=============================================================================================*/
495{
496 if (ProfileCollecting) {
497 float time=Get_Time_Since_Reset();
498 TotalFrameTimes+=time;
500 new_root->Set_Total_Time(time);
501 new_root->Set_Total_Calls(1);
502 ProfileCollectVector.Add(new_root);
503 Reset();
504 }
505
506 FrameCounter++;
507
508}
509
510
511/***********************************************************************************************
512 * WWProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset *
513 * *
514 * INPUT: *
515 * *
516 * OUTPUT: *
517 * *
518 * WARNINGS: *
519 * *
520 * HISTORY: *
521 * 9/24/2000 gth : Created. *
522 *=============================================================================================*/
524{
525 __int64 time;
526 WWProfile_Get_Ticks(&time);
527 time -= ResetTime;
528
529 return float(double(time) * WWProfile_Get_Inv_Processor_Ticks_Per_Second());
530}
531
532
533/***********************************************************************************************
534 * WWProfileManager::Get_Iterator -- Creates an iterator for the profile tree *
535 * *
536 * INPUT: *
537 * *
538 * OUTPUT: *
539 * *
540 * WARNINGS: *
541 * *
542 * HISTORY: *
543 * 9/24/2000 gth : Created. *
544 *=============================================================================================*/
549
550
551/***********************************************************************************************
552 * WWProfileManager::Release_Iterator -- Return an iterator for the profile tree *
553 * *
554 * INPUT: *
555 * *
556 * OUTPUT: *
557 * *
558 * WARNINGS: *
559 * *
560 * HISTORY: *
561 * 9/24/2000 gth : Created. *
562 *=============================================================================================*/
564{
565 delete iterator;
566}
567
568
570{
571 Reset();
572 ProfileCollecting=true;
573 TotalFrameTimes=0.0;
574}
575
576void WWProfileManager::End_Collecting(const char* filename)
577{
578 int i;
579 if (filename && ProfileCollectVector.Count()!=0) {
580 FileClass * file= _TheWritingFileFactory->Get_File(filename);
581 if (file != NULL) {
582 //
583 // Open or create the file
584 //
585 file->Open (FileClass::WRITE);
586
587 StringClass str;
588 float avg_frame_time=TotalFrameTimes/float(ProfileCollectVector.Count());
589 str.Format(
590 "Total frames: %d, average frame time: %fms\r\n"
591 "All frames taking more than twice the average frame time are marked with keyword SPIKE.\r\n\r\n",
592 ProfileCollectVector.Count(),avg_frame_time*1000.0f);
593 file->Write(str.Peek_Buffer(),str.Get_Length());
594
595 HashTemplateIterator<StringClass,unsigned> ite(ProfileStringHash);
596 for (ite.First();!ite.Is_Done();ite.Next()) {
597 StringClass name=ite.Peek_Key();
598 // Remove spaces, tabs and commas from the name as it would confuse the profile browser
599 int i;
600 for (i=0;i<name.Get_Length();++i) {
601 if (name[i]=='\t') name[i]='-';
602 if (name[i]==' ') name[i]='_';
603 if (name[i]==',') name[i]='.';
604 if (name[i]==';') name[i]=':';
605 }
606 str.Format("ID: %d %s\r\n",ite.Peek_Value(),name);
607 file->Write(str.Peek_Buffer(),str.Get_Length());
608 }
609
610 str.Format("\r\n\r\n");
611 file->Write(str.Peek_Buffer(),str.Get_Length());
612
613 for (i=0;i<ProfileCollectVector.Count();++i) {
614 float frame_time=ProfileCollectVector[i]->Get_Total_Time();
615 str.Format("FRAME: %d %2.2f %s ",i,frame_time*1000.0f,frame_time>avg_frame_time*2.0f ? "SPIKE" : "OK");
616 ProfileCollectVector[i]->Add_To_String_Compact(str,0);
617 str+="\r\n";
618 file->Write(str.Peek_Buffer(),str.Get_Length());
619 }
620
621 //
622 // Close the file
623 //
624 file->Close ();
625 _TheWritingFileFactory->Return_File (file);
626 }
627 }
628
629 for (i=0;i<ProfileCollectVector.Count();++i) {
630 delete ProfileCollectVector[i];
631 ProfileCollectVector[i]=0;
632 }
633 ProfileCollectVector.Delete_All();
634 ProfileCollecting=false;
635}
636
637static unsigned Read_Line(char* memory,unsigned pos,unsigned maxpos)
638{
639 while (pos<maxpos) {
640 if (memory[pos++]=='\n') {
641 return pos;
642 }
643 }
644 return pos;
645}
646
647static unsigned Seek_Char(char* memory,unsigned pos,unsigned maxpos,char c)
648{
649 while (pos<maxpos) {
650 if (memory[pos++]==c) {
651 return pos;
652 }
653 }
654 return pos;
655}
656
657unsigned Read_Int(char* memory,unsigned pos,unsigned maxpos,unsigned& number)
658{
659 number=0;
660 while (pos<maxpos) {
661 char c=memory[pos++];
662 if (isdigit(c)) {
663 number*=10;
664 number+=c-'0';
665 }
666 else break;
667 }
668 return pos;
669}
670
671unsigned Read_String(char* memory,unsigned pos,unsigned maxpos,char* string)
672{
673 int ccount=0;
674 while (pos<maxpos) {
675 char c=memory[pos++];
676 if (c>' ') {
677 string[ccount++]=c;
678 }
679 else break;
680 }
681 string[ccount]='\0';
682 return pos;
683}
684
685unsigned Read_Float(char* memory,unsigned pos,unsigned maxpos,float& fnumber)
686{
687 unsigned ftint=0;
688 float ftfloat=0.0f;
689 while (pos<maxpos) {
690 char c=memory[pos++];
691 if (isdigit(c)) {
692 ftint*=10;
693 ftint+=c-'0';
694 }
695 else {
696 if (c=='.') {
697 float divider=1.0f;
698 while (pos<maxpos) {
699 char c=memory[pos++];
700 if (isdigit(c)) {
701 ftfloat*=10.0f;
702 ftfloat+=float(c-'0');
703 divider*=10.0f;
704 }
705 else break;
706 }
707 ftfloat/=divider;
708 }
709 break;
710 }
711 }
712 ftfloat+=float(ftint);
713 fnumber=ftfloat;
714
715 return pos;
716}
717
718static unsigned Read_ID(char* memory,unsigned pos,unsigned maxpos,StringClass& string,unsigned& id)
719{
720 char idstring[256];
721 unsigned idnumber=0;
722 pos+=4; // "ID: "
723
724 // Read idnumber
725 pos=Read_Int(memory,pos,maxpos,idnumber);
726 // Read name
727 pos=Read_String(memory,pos,maxpos,idstring);
728
729 string=idstring;
730 id=idnumber;
731
732 return Read_Line(memory,pos,maxpos);
733}
734
735static unsigned Read_Frame(char* memory,unsigned pos,unsigned maxpos,WWProfileHierachyInfoClass*& root,HashTemplateClass<unsigned, StringClass>& id_hash)
736{
737 char statusstring[256];
738 unsigned framenumber=0;
739 float frametime;
740 root=NULL;
743
744 pos+=7; // "FRAME: "
745
746 // Read frame number
747 pos=Read_Int(memory,pos,maxpos,framenumber);
748
749 // Read frametime
750 pos=Read_Float(memory,pos,maxpos,frametime);
751
752 // Read statusstring
753 pos=Read_String(memory,pos,maxpos,statusstring);
754
755 // Done with the header, read the fram data
756
757 unsigned lineend=Read_Line(memory,pos,maxpos);
758 while (pos<lineend) {
759 // A Digit?
760 if (isdigit(memory[pos])) {
761 unsigned id;
762 unsigned count;
763 float time;
764 // Read id
765 pos=Read_Int(memory,pos,maxpos,id);
766
767 // Read count
768 pos=Read_Int(memory,pos,maxpos,count);
769
770 // Read time
771 pos=Read_Float(memory,pos,maxpos,time);
772
773 StringClass name="Unknown";
774 id_hash.Get(id,name);
776 if (parent) {
777 new_node->Set_Sibling(parent->Get_Child());
778 parent->Set_Child(new_node);
779 }
780 new_node->Set_Total_Time(time);
781 new_node->Set_Total_Calls(count);
782 latest=new_node;
783 if (root==NULL) root=new_node;
784 }
785 else if (memory[pos]=='{') {
786 parent=latest;
787 pos++;
788 }
789 else if (memory[pos]=='}') {
790 if (parent) {
791 parent=parent->Get_Parent();
792 }
793 pos++;
794 }
795 else {
796 pos++;
797 }
798 }
799
800 return Read_Line(memory,pos,maxpos);
801}
802
803void WWProfileManager::Load_Profile_Log(const char* filename, WWProfileHierachyInfoClass**& array, unsigned& count)
804{
805 array=NULL;
806 count=0;
807
808 unsigned i;
809 FileClass * file= _TheFileFactory->Get_File(filename);
810 if (file != NULL && file->Is_Available()) {
814
815 //
816 // Open or create the file
817 //
818 file->Open (FileClass::READ);
819 char tmp[256];
820
821 unsigned size=file->Size();
822 char* memory=new char[size];
823 file->Read(memory,size);
824 file->Close();
825 unsigned pos=0;
826
827 while (pos<size) {
828 Read_String(memory,pos,size,tmp);
829 if (tmp[0]=='I' && tmp[1]=='D' && tmp[2]==':') {
830 StringClass string;
831 unsigned id;
832 pos=Read_ID(memory,pos,size,string,id);
833 string_hash.Insert(string,id);
834 id_hash.Insert(id,string);
835 }
836 else if (tmp[0]=='F' && tmp[1]=='R' && tmp[2]=='A' && tmp[3]=='M' && tmp[4]=='E' && tmp[5]==':') {
838 pos=Read_Frame(memory,pos,size,node,id_hash);
839 if (node) {
840 vec.Add(node);
841 }
842 }
843 else {
844 pos=Read_Line(memory,pos,size);
845 }
846 }
847 delete[] memory;
848
849 if (vec.Count()) {
850 count=vec.Count();
851 array=new WWProfileHierachyInfoClass*[count];
852 for (i=0;i<count;++i) {
853 array[i]=vec[i];
854 }
855 }
856 }
857}
858
859
860/***********************************************************************************************
861 * WWProfileManager::Get_In_Order_Iterator -- Creates an "in-order" iterator for the profile t *
862 * *
863 * INPUT: *
864 * *
865 * OUTPUT: *
866 * *
867 * WARNINGS: *
868 * *
869 * HISTORY: *
870 * 9/24/2000 gth : Created. *
871 *=============================================================================================*/
876
877
878/***********************************************************************************************
879 * WWProfileManager::Release_In_Order_Iterator -- Return an "in-order" iterator *
880 * *
881 * INPUT: *
882 * *
883 * OUTPUT: *
884 * *
885 * WARNINGS: *
886 * *
887 * HISTORY: *
888 * 9/24/2000 gth : Created. *
889 *=============================================================================================*/
891{
892 delete iterator;
893}
894
895
896/***************************************************************************************************
897**
898** WWProfileIterator Implementation
899**
900***************************************************************************************************/
906
908{
909 CurrentChild = CurrentParent->Get_Child();
910}
911
912
914{
915 CurrentChild = CurrentChild->Get_Sibling();
916}
917
919{
920 return CurrentChild == NULL;
921}
922
928
930{
931 CurrentChild = CurrentParent->Get_Child();
932 while ( (CurrentChild != NULL) && (index != 0) ) {
933 index--;
934 CurrentChild = CurrentChild->Get_Sibling();
935 }
936
937 if ( CurrentChild != NULL ) {
939 CurrentChild = CurrentParent->Get_Child();
940 }
941}
942
944{
945 if ( CurrentParent->Get_Parent() != NULL ) {
946 CurrentParent = CurrentParent->Get_Parent();
947 }
948 CurrentChild = CurrentParent->Get_Child();
949}
950
951/***************************************************************************************************
952**
953** WWProfileInOrderIterator Implementation
954**
955***************************************************************************************************/
956
958{
959 CurrentNode = &WWProfileManager::Root;
960}
961
963{
964 CurrentNode = &WWProfileManager::Root;
965}
966
968{
969 if ( CurrentNode->Get_Child() ) { // If I have a child, go to child
970 CurrentNode = CurrentNode->Get_Child();
971 } else if ( CurrentNode->Get_Sibling() ) { // If I have a sibling, go to sibling
972 CurrentNode = CurrentNode->Get_Sibling();
973 } else { // if not, go to my parent's sibling, or his.......
974 // Find a parent with a sibling....
975 bool done = false;
976 while ( CurrentNode != NULL && !done ) {
977
978 // go to my parent
979 CurrentNode = CurrentNode->Get_Parent();
980
981 // If I have a sibling, go there
982 if ( CurrentNode != NULL && CurrentNode->Get_Sibling() != NULL ) {
983 CurrentNode = CurrentNode->Get_Sibling();
984 done = true;
985 }
986 }
987 }
988}
989
991{
992 return CurrentNode == NULL;
993}
994
995/*
996**
997*/
999{
1000 Name = name;
1001 WWProfile_Get_Ticks( &Time );
1002}
1003
1005{
1006 __int64 End;
1007 WWProfile_Get_Ticks( &End );
1008 End -= Time;
1009#ifdef WWDEBUG
1011 WWDEBUG_SAY(( "*** WWTIMEIT *** %s took %1.9f\n", Name, time ));
1012#endif
1013}
1014
1015
1016/*
1017**
1018*/
1020{
1021 WWASSERT(p_result != NULL);
1022 PResult = p_result;
1023 WWProfile_Get_Ticks( &Time );
1024}
1025
1027{
1028 __int64 End;
1029 WWProfile_Get_Ticks( &End );
1030 End -= Time;
1031 WWASSERT(PResult != NULL);
1033}
1034
1035// ----------------------------------------------------------------------------
1036//
1037//
1038//
1039// ----------------------------------------------------------------------------
1040
1042
1044 :
1045 Name(name),
1047 AllocCountStart(FastAllocatorGeneral::Get_Allocator()->Get_Total_Allocation_Count()),
1048 AllocSizeStart(FastAllocatorGeneral::Get_Allocator()->Get_Total_Allocated_Size())
1049{
1053 StringClass tmp(0,true);
1054 for (unsigned i=0;i<TabCount;++i) tmp+="\t";
1055 WWRELEASE_SAY(("%s%s {\n",tmp,name));
1056 TabCount++;
1057}
1058
1060{
1061 if (TabCount>0) TabCount--;
1062 StringClass tmp(0,true);
1063 for (unsigned i=0;i<TabCount;++i) tmp+="\t";
1064 WWRELEASE_SAY(("%s} ",tmp));
1065
1066 unsigned current_time=WWProfile_Get_System_Time();
1069 WWRELEASE_SAY(("IN TOTAL %s took %d.%3.3d s, did %d memory allocations of %d bytes\n",
1070 Name,
1071 (current_time - TimeStart)/1000, (current_time - TimeStart)%1000,
1072 current_alloc_count - AllocCountStart,
1073 current_alloc_size - AllocSizeStart));
1074 WWRELEASE_SAY(("\n"));
1075
1076}
1077
1078
1080{
1081 unsigned current_time=WWProfile_Get_System_Time();
1084 StringClass tmp(0,true);
1085 for (unsigned i=0;i<TabCount;++i) tmp+="\t";
1086 WWRELEASE_SAY(("%s%s took %d.%3.3d s, did %d memory allocations of %d bytes\n",
1087 tmp,
1088 text,
1089 (current_time - IntermediateTimeStart)/1000, (current_time - IntermediateTimeStart)%1000,
1090 current_alloc_count - IntermediateAllocCountStart,
1091 current_alloc_size - IntermediateAllocSizeStart));
1092 IntermediateTimeStart=current_time;
1093 IntermediateAllocCountStart=current_alloc_count;
1094 IntermediateAllocSizeStart=current_alloc_size;
1095}
1096
1097/***********************************************************************************************
1098 * WWProfileHierachyInfoClass::WWProfileHierachyInfoClass -- Constructor *
1099 * *
1100 * *
1101 * INPUT: *
1102 * name - pointer to a static string which is the name of this profile node *
1103 * parent - parent pointer *
1104 * *
1105 * OUTPUT: *
1106 * *
1107 * WARNINGS: *
1108 * *
1109 * HISTORY: *
1110 *=============================================================================================*/
1112 Name( name ),
1113 TotalCalls( 0 ),
1114 TotalTime( 0 ),
1115 Parent( parent ),
1116 Child( NULL ),
1117 Sibling( NULL )
1118{
1119}
1120
1121/***********************************************************************************************
1122 * WWProfileHierachyNodeClass::~WWProfileHierachyNodeClass -- Destructor *
1123 * *
1124 * INPUT: *
1125 * *
1126 * OUTPUT: *
1127 * *
1128 * WARNINGS: *
1129 * *
1130 * HISTORY: *
1131 * 9/24/2000 gth : Created. *
1132 *=============================================================================================*/
1134{
1135 delete Child;
1136 delete Sibling;
1137}
1138
#define NULL
Definition BaseType.h:92
#define WWASSERT
#define W3DNEW
Definition always.h:109
#define WWINLINE
Definition always.h:172
static double Get_Inv_Processor_Ticks_Per_Second()
Definition cpudetect.h:172
static FastAllocatorGeneral * Get_Allocator()
unsigned Get_Total_Allocated_Size()
unsigned Get_Total_Allocation_Count()
virtual int Size(void)=0
virtual bool Is_Available(int forced=false)=0
virtual int Read(void *buffer, int size)=0
virtual void Close(void)=0
virtual int Open(char const *filename, int rights=READ)=0
virtual int Write(void const *buffer, int size)=0
@ WRITE
Definition WWFILE.H:72
ValueType Get(const KeyType &s) const
void Insert(const KeyType &s, const ValueType &d)
ValueType & Peek_Value()
const KeyType & Peek_Key()
int Count(void) const
Definition simplevec.h:263
bool Add(T const &object, int new_size_hint=0)
Definition simplevec.h:371
int _cdecl Format(const TCHAR *format,...)
Definition wwstring.cpp:273
int Get_Length(void) const
Definition wwstring.h:664
TCHAR * Peek_Buffer(void)
Definition wwstring.h:560
WWMeasureItClass(float *p_result)
WWProfileHierachyInfoClass * Sibling
Definition wwprofile.h:138
void Set_Sibling(WWProfileHierachyInfoClass *node)
Definition wwprofile.h:120
WWProfileHierachyInfoClass * Child
Definition wwprofile.h:137
WWProfileHierachyInfoClass(const char *name, WWProfileHierachyInfoClass *parent)
void Set_Total_Time(float time)
Definition wwprofile.h:128
void Set_Total_Calls(int calls)
Definition wwprofile.h:127
WWProfileHierachyInfoClass * Parent
Definition wwprofile.h:136
WWProfileHierachyNodeClass * Sibling
Definition wwprofile.h:107
void Add_To_String_Compact(StringClass &string, int recursion)
WWProfileHierachyNodeClass * Get_Sub_Node(const char *name)
WWProfileHierachyNodeClass(const char *name, WWProfileHierachyNodeClass *parent)
WWProfileHierachyNodeClass * Child
Definition wwprofile.h:106
void Write_To_File(FileClass *file, int recursion)
void Set_Total_Calls(int calls)
Definition wwprofile.h:88
void Set_Total_Time(float time)
Definition wwprofile.h:89
WWProfileHierachyNodeClass * Parent
Definition wwprofile.h:105
WWProfileHierachyNodeClass * Clone_Hierarchy(WWProfileHierachyNodeClass *parent)
WWProfileHierachyNodeClass * CurrentNode
Definition wwprofile.h:191
WWProfileIterator(WWProfileHierachyNodeClass *start)
WWProfileHierachyNodeClass * CurrentParent
Definition wwprofile.h:167
WWProfileHierachyNodeClass * CurrentChild
Definition wwprofile.h:168
bool Is_Done(void)
void Enter_Child(void)
void Enter_Parent(void)
static WWProfileIterator * Get_Iterator(void)
static void Release_In_Order_Iterator(WWProfileInOrderIterator *iterator)
static WWProfileInOrderIterator * Get_In_Order_Iterator(void)
static void Begin_Collecting()
static void Stop_Profile(void)
static void Start_Profile(const char *name)
static void Release_Iterator(WWProfileIterator *iterator)
static void Increment_Frame_Counter(void)
static void Load_Profile_Log(const char *filename, WWProfileHierachyInfoClass **&array, unsigned &count)
static void End_Collecting(const char *filename)
static void Start_Root_Profile(const char *name)
friend class WWProfileInOrderIterator
Definition wwprofile.h:237
static void Stop_Root_Profile(void)
static void Reset(void)
static float Get_Time_Since_Reset(void)
WWTimeItClass(const char *name)
RawFileFactoryClass * _TheWritingFileFactory
Definition ffactory.cpp:55
FileFactoryClass * _TheFileFactory
Definition ffactory.cpp:51
void recursion(int level)
Definition test1.cpp:56
static unsigned TabCount
Definition wwprofile.h:335
void Log_Intermediate(const char *text)
StringClass Name
Definition wwprofile.h:334
unsigned IntermediateTimeStart
Definition wwprofile.h:329
int IntermediateAllocSizeStart
Definition wwprofile.h:333
WWMemoryAndTimeLog(const char *name)
int IntermediateAllocCountStart
Definition wwprofile.h:331
#define TIMEGETTIME
Definition systimer.h:44
#define WWRELEASE_SAY(x)
Definition wwdebug.h:121
#define WWDEBUG_SAY(x)
Definition wwdebug.h:114
WWINLINE double WWProfile_Get_Inv_Processor_Ticks_Per_Second(void)
Definition wwprofile.cpp:78
unsigned Read_String(char *memory, unsigned pos, unsigned maxpos, char *string)
void WWProfile_Get_Ticks(_int64 *ticks)
Definition wwprofile.cpp:99
unsigned WWProfile_Get_System_Time()
Definition wwprofile.cpp:73
unsigned Read_Float(char *memory, unsigned pos, unsigned maxpos, float &fnumber)
unsigned Read_Int(char *memory, unsigned pos, unsigned maxpos, unsigned &number)
unsigned WWProfile_Get_System_Time()
Definition wwprofile.cpp:73