Cmd_AddCommand ("prvm_edicts", PRVM_ED_PrintEdicts_f, "prints all data about all entities in the selected VM (server, client, menu)");
Cmd_AddCommand ("prvm_edictcount", PRVM_ED_Count_f, "prints number of active entities in the selected VM (server, client, menu)");
Cmd_AddCommand ("prvm_profile", PRVM_Profile_f, "prints execution statistics about the most used QuakeC functions in the selected VM (server, client, menu)");
+ Cmd_AddCommand ("prvm_childprofile", PRVM_ChildProfile_f, "prints execution statistics about the most used QuakeC functions in the selected VM (server, client, menu), sorted by time taken in function with child calls");
Cmd_AddCommand ("prvm_callprofile", PRVM_CallProfile_f, "prints execution statistics about the most time consuming QuakeC calls from the engine in the selected VM (server, client, menu)");
Cmd_AddCommand ("prvm_fields", PRVM_Fields_f, "prints usage statistics on properties (how many entities have non-zero values) in the selected VM (server, client, menu)");
Cmd_AddCommand ("prvm_globals", PRVM_Globals_f, "prints all global variables in the selected VM (server, client, menu)");
prog->starttime = Sys_DoubleTime();
}
-void PRVM_Profile (int maxfunctions, int mininstructions)
+void PRVM_Profile (int maxfunctions, int mininstructions, int sortby)
{
mfunction_t *f, *best;
int i, num;
double max;
- Con_Printf( "%s Profile:\n[CallCount] [Statements] [BuiltinCost]\n", PRVM_NAME );
+ Con_Printf( "%s Profile:\n[CallCount] [Statement] [BuiltinCt] [StmtTotal] [BltnTotal] [self]\n", PRVM_NAME );
+ // 12345678901 12345678901 12345678901 12345678901 12345678901 123.45%
num = 0;
do
for (i=0 ; i<prog->progs->numfunctions ; i++)
{
f = &prog->functions[i];
- if (max < f->profile + f->builtinsprofile + f->callcount)
+ if(sortby)
{
- max = f->profile + f->builtinsprofile + f->callcount;
- best = f;
+ if (max < f->profile_total + f->builtinsprofile_total + f->callcount)
+ {
+ max = f->profile_total + f->builtinsprofile_total + f->callcount;
+ best = f;
+ }
+ }
+ else
+ {
+ if (max < f->profile + f->builtinsprofile + f->callcount)
+ {
+ max = f->profile + f->builtinsprofile + f->callcount;
+ best = f;
+ }
}
}
if (best)
if (num < maxfunctions && max >= mininstructions)
{
if (best->first_statement < 0)
- Con_Printf("%9.0f ----- builtin ----- %s\n", best->callcount, PRVM_GetString(best->s_name));
+ Con_Printf("%11.0f ----------------------- builtin ----------------------- %s\n", best->callcount, PRVM_GetString(best->s_name));
+ // 12345678901 12345678901 12345678901 12345678901 123.45%
else
- Con_Printf("%9.0f %9.0f %9.0f %s\n", best->callcount, best->profile, best->builtinsprofile, PRVM_GetString(best->s_name));
+ Con_Printf("%11.0f %11.0f %11.0f %11.0f %11.0f %6.2f%% %s\n", best->callcount, best->profile, best->builtinsprofile, best->profile_total, best->builtinsprofile_total, (best->profile + best->builtinsprofile) * 100.0 / (best->profile_total + best->builtinsprofile_total), PRVM_GetString(best->s_name));
}
num++;
best->profile = 0;
best->builtinsprofile = 0;
+ best->profile_total = 0;
+ best->builtinsprofile_total = 0;
best->callcount = 0;
}
} while (best);
if(!PRVM_SetProgFromString(Cmd_Argv(1)))
return;
- PRVM_Profile(howmany, 1);
+ PRVM_Profile(howmany, 1, 0);
+
+ PRVM_End;
+}
+
+void PRVM_ChildProfile_f (void)
+{
+ int howmany;
+
+ howmany = 1<<30;
+ if (Cmd_Argc() == 3)
+ howmany = atoi(Cmd_Argv(2));
+ else if (Cmd_Argc() != 2)
+ {
+ Con_Print("prvm_childprofile <program name>\n");
+ return;
+ }
+
+ PRVM_Begin;
+ if(!PRVM_SetProgFromString(Cmd_Argv(1)))
+ return;
+
+ PRVM_Profile(howmany, 1, 1);
PRVM_End;
}
prog->stack[prog->depth].s = prog->xstatement;
prog->stack[prog->depth].f = prog->xfunction;
+ prog->stack[prog->depth].profile_acc = -f->profile;
+ prog->stack[prog->depth].builtinsprofile_acc = -f->builtinsprofile;
prog->depth++;
if (prog->depth >=PRVM_MAX_STACK_DEPTH)
PRVM_ERROR ("stack overflow");
}
}
+ ++f->recursion;
prog->xfunction = f;
return f->first_statement - 1; // offset the s++
}
int PRVM_LeaveFunction (void)
{
int i, c;
+ mfunction_t *f;
if (prog->depth <= 0)
PRVM_ERROR ("prog stack underflow in %s", PRVM_NAME);
// up stack
prog->depth--;
+ f = prog->xfunction;
+ --f->recursion;
prog->xfunction = prog->stack[prog->depth].f;
+ prog->stack[prog->depth].profile_acc += f->profile;
+ prog->stack[prog->depth].builtinsprofile_acc += f->builtinsprofile;
+ if(prog->depth > 0)
+ {
+ prog->stack[prog->depth-1].profile_acc += prog->stack[prog->depth].profile_acc;
+ prog->stack[prog->depth-1].builtinsprofile_acc += prog->stack[prog->depth].builtinsprofile_acc;
+ }
+ if(!f->recursion)
+ {
+ // if f is already on the call stack...
+ // we cannot add this profile data to it now
+ // or we would add it more than once
+ // so, let's only add to the function's profile if it is the outermost call
+ f->profile_total += prog->stack[prog->depth].profile_acc;
+ f->builtinsprofile_total += prog->stack[prog->depth].builtinsprofile_acc;
+ }
+
return prog->stack[prog->depth].s;
}
if (++jumpcount == 10000000)
{
prog->xstatement = st - prog->statements;
- PRVM_Profile(1<<30, 1000000);
+ PRVM_Profile(1<<30, 1000000, 0);
PRVM_ERROR("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", PRVM_NAME, jumpcount);
}
#endif
if (++jumpcount == 10000000)
{
prog->xstatement = st - prog->statements;
- PRVM_Profile(1<<30, 1000000);
+ PRVM_Profile(1<<30, 1000000, 0);
PRVM_ERROR("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", PRVM_NAME, jumpcount);
}
#endif
if (++jumpcount == 10000000)
{
prog->xstatement = st - prog->statements;
- PRVM_Profile(1<<30, 1000000);
+ PRVM_Profile(1<<30, 1000000, 0);
PRVM_ERROR("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", PRVM_NAME, jumpcount);
}
#endif