mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-12-01 00:21:43 +00:00
- More options for acsprofile command:
* acsprofile clear - Resets all profiling statistics to 0. * acsprofile [<sort-function>] [<limit>]: * <sort-function> is an optional argument that specifies which column to sort on (total, min, max, avg, or runs). The default is total. * <limit> is an optional argument that specifies how many rows to limit the output to. The default is 10. 0 or less will print every script or function that has at least one run. SVN r4060 (trunk)
This commit is contained in:
parent
b971714e7f
commit
f68d5a4845
2 changed files with 113 additions and 18 deletions
130
src/p_acs.cpp
130
src/p_acs.cpp
|
@ -7715,6 +7715,11 @@ void DACSThinker::DumpScriptStatus ()
|
||||||
// Profiling support --------------------------------------------------------
|
// Profiling support --------------------------------------------------------
|
||||||
|
|
||||||
ACSProfileInfo::ACSProfileInfo()
|
ACSProfileInfo::ACSProfileInfo()
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ACSProfileInfo::Reset()
|
||||||
{
|
{
|
||||||
TotalInstr = 0;
|
TotalInstr = 0;
|
||||||
NumRuns = 0;
|
NumRuns = 0;
|
||||||
|
@ -7772,6 +7777,14 @@ void ArrangeFunctionProfiles(TArray<ProfileCollector> &profiles)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClearProfiles(TArray<ProfileCollector> &profiles)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < profiles.Size(); ++i)
|
||||||
|
{
|
||||||
|
profiles[i].ProfileData->Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int STACK_ARGS sort_by_total_instr(const void *a_, const void *b_)
|
static int STACK_ARGS sort_by_total_instr(const void *a_, const void *b_)
|
||||||
{
|
{
|
||||||
const ProfileCollector *a = (const ProfileCollector *)a_;
|
const ProfileCollector *a = (const ProfileCollector *)a_;
|
||||||
|
@ -7782,7 +7795,42 @@ static int STACK_ARGS sort_by_total_instr(const void *a_, const void *b_)
|
||||||
return (int)(b->ProfileData->TotalInstr - a->ProfileData->TotalInstr);
|
return (int)(b->ProfileData->TotalInstr - a->ProfileData->TotalInstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ShowProfileData(TArray<ProfileCollector> &profiles, long ilimit, bool functions)
|
static int STACK_ARGS sort_by_min(const void *a_, const void *b_)
|
||||||
|
{
|
||||||
|
const ProfileCollector *a = (const ProfileCollector *)a_;
|
||||||
|
const ProfileCollector *b = (const ProfileCollector *)b_;
|
||||||
|
|
||||||
|
return b->ProfileData->MinInstrPerRun - a->ProfileData->MinInstrPerRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int STACK_ARGS sort_by_max(const void *a_, const void *b_)
|
||||||
|
{
|
||||||
|
const ProfileCollector *a = (const ProfileCollector *)a_;
|
||||||
|
const ProfileCollector *b = (const ProfileCollector *)b_;
|
||||||
|
|
||||||
|
return b->ProfileData->MaxInstrPerRun - a->ProfileData->MaxInstrPerRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int STACK_ARGS sort_by_avg(const void *a_, const void *b_)
|
||||||
|
{
|
||||||
|
const ProfileCollector *a = (const ProfileCollector *)a_;
|
||||||
|
const ProfileCollector *b = (const ProfileCollector *)b_;
|
||||||
|
|
||||||
|
int a_avg = a->ProfileData->NumRuns == 0 ? 0 : int(a->ProfileData->TotalInstr / a->ProfileData->NumRuns);
|
||||||
|
int b_avg = b->ProfileData->NumRuns == 0 ? 0 : int(b->ProfileData->TotalInstr / b->ProfileData->NumRuns);
|
||||||
|
return b_avg - a_avg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int STACK_ARGS sort_by_runs(const void *a_, const void *b_)
|
||||||
|
{
|
||||||
|
const ProfileCollector *a = (const ProfileCollector *)a_;
|
||||||
|
const ProfileCollector *b = (const ProfileCollector *)b_;
|
||||||
|
|
||||||
|
return b->ProfileData->NumRuns - a->ProfileData->NumRuns;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ShowProfileData(TArray<ProfileCollector> &profiles, long ilimit,
|
||||||
|
int (STACK_ARGS *sorter)(const void *, const void *), bool functions)
|
||||||
{
|
{
|
||||||
static const char *const typelabels[2] = { "script", "function" };
|
static const char *const typelabels[2] = { "script", "function" };
|
||||||
|
|
||||||
|
@ -7795,7 +7843,7 @@ static void ShowProfileData(TArray<ProfileCollector> &profiles, long ilimit, boo
|
||||||
char modname[13];
|
char modname[13];
|
||||||
char scriptname[21];
|
char scriptname[21];
|
||||||
|
|
||||||
qsort(&profiles[0], profiles.Size(), sizeof(ProfileCollector), sort_by_total_instr);
|
qsort(&profiles[0], profiles.Size(), sizeof(ProfileCollector), sorter);
|
||||||
|
|
||||||
if (ilimit > 0)
|
if (ilimit > 0)
|
||||||
{
|
{
|
||||||
|
@ -7808,7 +7856,7 @@ static void ShowProfileData(TArray<ProfileCollector> &profiles, long ilimit, boo
|
||||||
limit = UINT_MAX;
|
limit = UINT_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
Printf(TEXTCOLOR_YELLOW "Module %-20s Total NumRuns Min Max Avg\n", typelabels[functions]);
|
Printf(TEXTCOLOR_YELLOW "Module %-20s Total Runs Avg Min Max\n", typelabels[functions]);
|
||||||
Printf(TEXTCOLOR_YELLOW "------------ -------------------- ---------- ------- ------- ------- -------\n");
|
Printf(TEXTCOLOR_YELLOW "------------ -------------------- ---------- ------- ------- ------- -------\n");
|
||||||
for (unsigned int i = 0; i < limit && i < profiles.Size(); ++i)
|
for (unsigned int i = 0; i < limit && i < profiles.Size(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -7820,16 +7868,7 @@ static void ShowProfileData(TArray<ProfileCollector> &profiles, long ilimit, boo
|
||||||
|
|
||||||
// Module name
|
// Module name
|
||||||
mysnprintf(modname, sizeof(modname), prof->Module->GetModuleName());
|
mysnprintf(modname, sizeof(modname), prof->Module->GetModuleName());
|
||||||
#if 0
|
|
||||||
if (prof->Module == FBehavior::StaticGetModule(0))
|
|
||||||
{
|
|
||||||
mysnprintf(modname, sizeof(modname), "<Map Script>");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mysnprintf(modname, sizeof(modname), Wads.GetLumpFullName(prof->Module->GetLumpNum()));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// Script/function name
|
// Script/function name
|
||||||
if (functions)
|
if (functions)
|
||||||
{
|
{
|
||||||
|
@ -7853,25 +7892,80 @@ static void ShowProfileData(TArray<ProfileCollector> &profiles, long ilimit, boo
|
||||||
modname, scriptname,
|
modname, scriptname,
|
||||||
prof->ProfileData->TotalInstr,
|
prof->ProfileData->TotalInstr,
|
||||||
prof->ProfileData->NumRuns,
|
prof->ProfileData->NumRuns,
|
||||||
|
unsigned(prof->ProfileData->TotalInstr / prof->ProfileData->NumRuns),
|
||||||
prof->ProfileData->MinInstrPerRun,
|
prof->ProfileData->MinInstrPerRun,
|
||||||
prof->ProfileData->MaxInstrPerRun,
|
prof->ProfileData->MaxInstrPerRun
|
||||||
prof->ProfileData->TotalInstr / prof->ProfileData->NumRuns);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CCMD(acsprofile)
|
CCMD(acsprofile)
|
||||||
{
|
{
|
||||||
|
static int (STACK_ARGS *sort_funcs[])(const void*, const void *) =
|
||||||
|
{
|
||||||
|
sort_by_total_instr,
|
||||||
|
sort_by_min,
|
||||||
|
sort_by_max,
|
||||||
|
sort_by_avg,
|
||||||
|
sort_by_runs
|
||||||
|
};
|
||||||
|
static const char *sort_names[] = { "total", "min", "max", "avg", "runs" };
|
||||||
|
static const BYTE sort_match_len[] = { 1, 2, 2, 1, 1 };
|
||||||
|
|
||||||
TArray<ProfileCollector> ScriptProfiles, FuncProfiles;
|
TArray<ProfileCollector> ScriptProfiles, FuncProfiles;
|
||||||
long limit = 10;
|
long limit = 10;
|
||||||
|
int (STACK_ARGS *sorter)(const void *, const void *) = sort_by_total_instr;
|
||||||
|
|
||||||
|
assert(countof(sort_names) == countof(sort_match_len));
|
||||||
|
|
||||||
ArrangeScriptProfiles(ScriptProfiles);
|
ArrangeScriptProfiles(ScriptProfiles);
|
||||||
ArrangeFunctionProfiles(FuncProfiles);
|
ArrangeFunctionProfiles(FuncProfiles);
|
||||||
|
|
||||||
if (argv.argc() > 1)
|
if (argv.argc() > 1)
|
||||||
{
|
{
|
||||||
limit = strtol(argv[1], NULL, 0);
|
// `acsprofile clear` will zero all profiling information collected so far.
|
||||||
|
if (stricmp(argv[1], "clear") == 0)
|
||||||
|
{
|
||||||
|
ClearProfiles(ScriptProfiles);
|
||||||
|
ClearProfiles(FuncProfiles);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = 1; i < argv.argc(); ++i)
|
||||||
|
{
|
||||||
|
// If it's a number, set the display limit.
|
||||||
|
char *endptr;
|
||||||
|
long num = strtol(argv[i], &endptr, 0);
|
||||||
|
if (endptr != argv[i])
|
||||||
|
{
|
||||||
|
limit = num;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// If it's a name, set the sort method. We accept partial matches for
|
||||||
|
// options that are shorter than the sort name.
|
||||||
|
size_t optlen = strlen(argv[i]);
|
||||||
|
int j;
|
||||||
|
for (j = 0; j < countof(sort_names); ++j)
|
||||||
|
{
|
||||||
|
if (optlen < sort_match_len[j] || optlen > strlen(sort_names[j]))
|
||||||
|
{ // Too short or long to match.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strnicmp(argv[i], sort_names[j], optlen) == 0)
|
||||||
|
{
|
||||||
|
sorter = sort_funcs[j];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j == countof(sort_names))
|
||||||
|
{
|
||||||
|
Printf("Unknown option '%s'\n", argv[i]);
|
||||||
|
Printf("acsprofile clear : Reset profiling information\n");
|
||||||
|
Printf("acsprofile [total|min|max|avg|runs] [<limit>]\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ShowProfileData(ScriptProfiles, limit, false);
|
ShowProfileData(ScriptProfiles, limit, sorter, false);
|
||||||
ShowProfileData(FuncProfiles, limit, true);
|
ShowProfileData(FuncProfiles, limit, sorter, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,7 @@ struct ACSProfileInfo
|
||||||
|
|
||||||
ACSProfileInfo();
|
ACSProfileInfo();
|
||||||
void AddRun(unsigned int num_instr);
|
void AddRun(unsigned int num_instr);
|
||||||
|
void Reset();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ProfileCollector
|
struct ProfileCollector
|
||||||
|
|
Loading…
Reference in a new issue