mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-28 15:02:01 +00:00
- added per-class think time profiling tool.
This commit is contained in:
parent
490e873602
commit
579840987d
2 changed files with 107 additions and 11 deletions
117
src/dthinker.cpp
117
src/dthinker.cpp
|
@ -462,6 +462,21 @@ void DThinker::DestroyThinkersInList (FThinkerList &list)
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
CVAR(Bool, profilethinkers, false, 0)
|
||||||
|
|
||||||
|
struct ProfileInfo
|
||||||
|
{
|
||||||
|
int numcalls = 0;
|
||||||
|
cycle_t timer;
|
||||||
|
|
||||||
|
ProfileInfo()
|
||||||
|
{
|
||||||
|
timer.Reset();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TMap<FName, ProfileInfo> Profiles;
|
||||||
|
|
||||||
|
|
||||||
void DThinker::RunThinkers ()
|
void DThinker::RunThinkers ()
|
||||||
{
|
{
|
||||||
|
@ -475,21 +490,50 @@ void DThinker::RunThinkers ()
|
||||||
|
|
||||||
ThinkCycles.Clock();
|
ThinkCycles.Clock();
|
||||||
|
|
||||||
// Tick every thinker left from last time
|
if (!profilethinkers)
|
||||||
for (i = STAT_FIRST_THINKING; i <= MAX_STATNUM; ++i)
|
|
||||||
{
|
{
|
||||||
TickThinkers (&Thinkers[i], NULL);
|
// Tick every thinker left from last time
|
||||||
}
|
|
||||||
|
|
||||||
// Keep ticking the fresh thinkers until there are no new ones.
|
|
||||||
do
|
|
||||||
{
|
|
||||||
count = 0;
|
|
||||||
for (i = STAT_FIRST_THINKING; i <= MAX_STATNUM; ++i)
|
for (i = STAT_FIRST_THINKING; i <= MAX_STATNUM; ++i)
|
||||||
{
|
{
|
||||||
count += TickThinkers (&FreshThinkers[i], &Thinkers[i]);
|
TickThinkers(&Thinkers[i], NULL);
|
||||||
}
|
}
|
||||||
} while (count != 0);
|
|
||||||
|
// Keep ticking the fresh thinkers until there are no new ones.
|
||||||
|
do
|
||||||
|
{
|
||||||
|
count = 0;
|
||||||
|
for (i = STAT_FIRST_THINKING; i <= MAX_STATNUM; ++i)
|
||||||
|
{
|
||||||
|
count += TickThinkers(&FreshThinkers[i], &Thinkers[i]);
|
||||||
|
}
|
||||||
|
} while (count != 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Profiles.Clear();
|
||||||
|
// Tick every thinker left from last time
|
||||||
|
for (i = STAT_FIRST_THINKING; i <= MAX_STATNUM; ++i)
|
||||||
|
{
|
||||||
|
ProfileThinkers(&Thinkers[i], NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep ticking the fresh thinkers until there are no new ones.
|
||||||
|
do
|
||||||
|
{
|
||||||
|
count = 0;
|
||||||
|
for (i = STAT_FIRST_THINKING; i <= MAX_STATNUM; ++i)
|
||||||
|
{
|
||||||
|
count += ProfileThinkers(&FreshThinkers[i], &Thinkers[i]);
|
||||||
|
}
|
||||||
|
} while (count != 0);
|
||||||
|
auto it = TMap<FName, ProfileInfo>::Iterator(Profiles);
|
||||||
|
TMap<FName, ProfileInfo>::Pair *pair;
|
||||||
|
while (it.NextPair(pair))
|
||||||
|
{
|
||||||
|
Printf("%s, %dx, %fms\n", pair->Key.GetChars(), pair->Value.numcalls, pair->Value.timer.TimeMS());
|
||||||
|
}
|
||||||
|
profilethinkers = false;
|
||||||
|
}
|
||||||
|
|
||||||
ThinkCycles.Unclock();
|
ThinkCycles.Unclock();
|
||||||
}
|
}
|
||||||
|
@ -541,6 +585,57 @@ int DThinker::TickThinkers (FThinkerList *list, FThinkerList *dest)
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
int DThinker::ProfileThinkers(FThinkerList *list, FThinkerList *dest)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
DThinker *node = list->GetHead();
|
||||||
|
|
||||||
|
if (node == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (node != list->Sentinel)
|
||||||
|
{
|
||||||
|
++count;
|
||||||
|
NextToThink = node->NextThinker;
|
||||||
|
if (node->ObjectFlags & OF_JustSpawned)
|
||||||
|
{
|
||||||
|
// Leave OF_JustSpawn set until after Tick() so the ticker can check it.
|
||||||
|
if (dest != NULL)
|
||||||
|
{ // Move thinker from this list to the destination list
|
||||||
|
node->Remove();
|
||||||
|
dest->AddTail(node);
|
||||||
|
}
|
||||||
|
node->CallPostBeginPlay();
|
||||||
|
}
|
||||||
|
else if (dest != NULL)
|
||||||
|
{
|
||||||
|
I_Error("There is a thinker in the fresh list that has already ticked.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(node->ObjectFlags & OF_EuthanizeMe))
|
||||||
|
{ // Only tick thinkers not scheduled for destruction
|
||||||
|
ThinkCount++;
|
||||||
|
|
||||||
|
auto &prof = Profiles[node->GetClass()->TypeName];
|
||||||
|
prof.numcalls++;
|
||||||
|
prof.timer.Clock();
|
||||||
|
node->CallTick();
|
||||||
|
prof.timer.Unclock();
|
||||||
|
node->ObjectFlags &= ~OF_JustSpawned;
|
||||||
|
GC::CheckGC();
|
||||||
|
}
|
||||||
|
node = NextToThink;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
|
@ -97,6 +97,7 @@ public:
|
||||||
private:
|
private:
|
||||||
static void DestroyThinkersInList (FThinkerList &list);
|
static void DestroyThinkersInList (FThinkerList &list);
|
||||||
static int TickThinkers (FThinkerList *list, FThinkerList *dest); // Returns: # of thinkers ticked
|
static int TickThinkers (FThinkerList *list, FThinkerList *dest); // Returns: # of thinkers ticked
|
||||||
|
static int ProfileThinkers(FThinkerList *list, FThinkerList *dest);
|
||||||
static void SaveList(FSerializer &arc, DThinker *node);
|
static void SaveList(FSerializer &arc, DThinker *node);
|
||||||
void Remove();
|
void Remove();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue