Bug 281137 Add profiling column for functions excluding other functions running

jsd part
patch by silver@warwickcompsoc.co.uk r=shaver sr=dmose a=bsmedberg
This commit is contained in:
timeless%mozdev.org 2005-08-02 15:53:59 +00:00
parent 543835b5eb
commit d2b31f1255
7 changed files with 190 additions and 4 deletions

View File

@ -78,7 +78,7 @@ interface jsdIProperty;
* Debugger service. It's not a good idea to have more than one active client of * Debugger service. It's not a good idea to have more than one active client of
* the debugger service. * the debugger service.
*/ */
[scriptable, uuid(01be7f9a-1dd2-11b2-9d55-aaf919b27c73)] [scriptable, uuid(9dd9006a-4e5e-4a80-ac3d-007fb7335ca4)]
interface jsdIDebuggerService : nsISupports interface jsdIDebuggerService : nsISupports
{ {
/** Internal use only. */ /** Internal use only. */
@ -954,6 +954,21 @@ interface jsdIScript : jsdIEphemeral
* Total time spent in this function, in milliseconds. * Total time spent in this function, in milliseconds.
*/ */
readonly attribute double totalExecutionTime; readonly attribute double totalExecutionTime;
/**
* Shortest execution time recorded, in milliseconds, excluding time spent
* in other called code.
*/
readonly attribute double minOwnExecutionTime;
/**
* Longest execution time recorded, in milliseconds, excluding time spent
* in other called code.
*/
readonly attribute double maxOwnExecutionTime;
/**
* Total time spent in this function, in milliseconds, excluding time spent
* in other called code.
*/
readonly attribute double totalOwnExecutionTime;
/** /**
* Clear profile data for this script. * Clear profile data for this script.

View File

@ -170,6 +170,8 @@ struct JSDContext
JSHashTable* atoms; JSHashTable* atoms;
JSCList objectsList; JSCList objectsList;
JSHashTable* objectsTable; JSHashTable* objectsTable;
JSDProfileData* callingFunctionPData;
int64 lastReturnTime;
#ifdef JSD_THREADSAFE #ifdef JSD_THREADSAFE
void* scriptsLock; void* scriptsLock;
void* sourceTextLock; void* sourceTextLock;
@ -206,13 +208,18 @@ struct JSDScript
struct JSDProfileData struct JSDProfileData
{ {
JSDProfileData* caller;
int64 lastCallStart; int64 lastCallStart;
int64 runningTime;
uintN callCount; uintN callCount;
uintN recurseDepth; uintN recurseDepth;
uintN maxRecurseDepth; uintN maxRecurseDepth;
jsdouble minExecutionTime; jsdouble minExecutionTime;
jsdouble maxExecutionTime; jsdouble maxExecutionTime;
jsdouble totalExecutionTime; jsdouble totalExecutionTime;
jsdouble minOwnExecutionTime;
jsdouble maxOwnExecutionTime;
jsdouble totalOwnExecutionTime;
}; };
struct JSDSourceText struct JSDSourceText
@ -409,6 +416,15 @@ jsd_GetScriptMaxExecutionTime(JSDContext* jsdc, JSDScript *script);
extern jsdouble extern jsdouble
jsd_GetScriptTotalExecutionTime(JSDContext* jsdc, JSDScript *script); jsd_GetScriptTotalExecutionTime(JSDContext* jsdc, JSDScript *script);
extern jsdouble
jsd_GetScriptMinOwnExecutionTime(JSDContext* jsdc, JSDScript *script);
extern jsdouble
jsd_GetScriptMaxOwnExecutionTime(JSDContext* jsdc, JSDScript *script);
extern jsdouble
jsd_GetScriptTotalOwnExecutionTime(JSDContext* jsdc, JSDScript *script);
extern void extern void
jsd_ClearScriptProfileData(JSDContext* jsdc, JSDScript *script); jsd_ClearScriptProfileData(JSDContext* jsdc, JSDScript *script);

View File

@ -353,6 +353,33 @@ jsd_GetScriptTotalExecutionTime(JSDContext* jsdc, JSDScript *script)
return 0.0; return 0.0;
} }
jsdouble
jsd_GetScriptMinOwnExecutionTime(JSDContext* jsdc, JSDScript *script)
{
if (script->profileData)
return script->profileData->minOwnExecutionTime;
return 0.0;
}
jsdouble
jsd_GetScriptMaxOwnExecutionTime(JSDContext* jsdc, JSDScript *script)
{
if (script->profileData)
return script->profileData->maxOwnExecutionTime;
return 0.0;
}
jsdouble
jsd_GetScriptTotalOwnExecutionTime(JSDContext* jsdc, JSDScript *script)
{
if (script->profileData)
return script->profileData->totalOwnExecutionTime;
return 0.0;
}
void void
jsd_ClearScriptProfileData(JSDContext* jsdc, JSDScript *script) jsd_ClearScriptProfileData(JSDContext* jsdc, JSDScript *script)
{ {

View File

@ -151,11 +151,38 @@ _callHook(JSDContext *jsdc, JSContext *cx, JSStackFrame *fp, JSBool before,
{ {
if (JSLL_IS_ZERO(pdata->lastCallStart)) if (JSLL_IS_ZERO(pdata->lastCallStart))
{ {
pdata->lastCallStart = JS_Now(); int64 now;
JSDProfileData *callerpdata;
/* Get the time just the once, for consistency. */
now = JS_Now();
/* This contains a pointer to the profile data for
* the caller of this function. */
callerpdata = jsdc->callingFunctionPData;
if (callerpdata)
{
int64 ll_delta;
pdata->caller = callerpdata;
/* We need to 'stop' the timer for the caller.
* Use time since last return if appropriate. */
if (JSLL_IS_ZERO(jsdc->lastReturnTime))
JSLL_SUB(ll_delta, now, callerpdata->lastCallStart);
else
JSLL_SUB(ll_delta, now, jsdc->lastReturnTime);
callerpdata->runningTime += ll_delta;
}
/* We're the new current function, and no return
* has happened yet. */
jsdc->callingFunctionPData = pdata;
jsdc->lastReturnTime = 0;
/* This function has no running time (just been
* called!), and we'll need the call start time. */
pdata->runningTime = JSLL_ZERO;
pdata->lastCallStart = now;
} else { } else {
if (++pdata->recurseDepth > pdata->maxRecurseDepth) if (++pdata->recurseDepth > pdata->maxRecurseDepth)
pdata->maxRecurseDepth = pdata->recurseDepth; pdata->maxRecurseDepth = pdata->recurseDepth;
} }
/* make sure we're called for the return too. */ /* make sure we're called for the return too. */
hookresult = JS_TRUE; hookresult = JS_TRUE;
} else if (!pdata->recurseDepth && } else if (!pdata->recurseDepth &&
@ -167,13 +194,48 @@ _callHook(JSDContext *jsdc, JSContext *cx, JSStackFrame *fp, JSBool before,
JSLL_L2D(delta, ll_delta); JSLL_L2D(delta, ll_delta);
delta /= 1000.0; delta /= 1000.0;
pdata->totalExecutionTime += delta; pdata->totalExecutionTime += delta;
if (!pdata->minExecutionTime || /* minExecutionTime starts as 0, so we need to overwrite
* it on the first call always. */
if ((0 == pdata->callCount) ||
delta < pdata->minExecutionTime) delta < pdata->minExecutionTime)
{ {
pdata->minExecutionTime = delta; pdata->minExecutionTime = delta;
} }
if (delta > pdata->maxExecutionTime) if (delta > pdata->maxExecutionTime)
pdata->maxExecutionTime = delta; pdata->maxExecutionTime = delta;
/* If we last returned from a function (as opposed to
* having last entered this function), we need to inc.
* the running total by the time delta since the last
* return, and use the running total instead of the
* delta calculated above. */
if (!JSLL_IS_ZERO(jsdc->lastReturnTime))
{
// Add last chunk to running time, and use total
// running time as 'delta'.
JSLL_SUB(ll_delta, now, jsdc->lastReturnTime);
pdata->runningTime += ll_delta;
JSLL_L2D(delta, pdata->runningTime);
delta /= 1000.0;
}
pdata->totalOwnExecutionTime += delta;
/* See minExecutionTime comment above. */
if ((0 == pdata->callCount) ||
delta < pdata->minOwnExecutionTime)
{
pdata->minOwnExecutionTime = delta;
}
if (delta > pdata->maxOwnExecutionTime)
pdata->maxOwnExecutionTime = delta;
/* Current function is now our caller. */
jsdc->callingFunctionPData = pdata->caller;
/* No hanging pointers, please. */
pdata->caller = NULL;
/* Mark the time we returned, and indicate this
* function is no longer running. */
jsdc->lastReturnTime = now;
pdata->lastCallStart = JSLL_ZERO; pdata->lastCallStart = JSLL_ZERO;
++pdata->callCount; ++pdata->callCount;
} else if (pdata->recurseDepth) { } else if (pdata->recurseDepth) {

View File

@ -1332,6 +1332,30 @@ jsdScript::GetTotalExecutionTime(double *_rval)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
jsdScript::GetMinOwnExecutionTime(double *_rval)
{
ASSERT_VALID_EPHEMERAL;
*_rval = JSD_GetScriptMinOwnExecutionTime (mCx, mScript);
return NS_OK;
}
NS_IMETHODIMP
jsdScript::GetMaxOwnExecutionTime(double *_rval)
{
ASSERT_VALID_EPHEMERAL;
*_rval = JSD_GetScriptMaxOwnExecutionTime (mCx, mScript);
return NS_OK;
}
NS_IMETHODIMP
jsdScript::GetTotalOwnExecutionTime(double *_rval)
{
ASSERT_VALID_EPHEMERAL;
*_rval = JSD_GetScriptTotalOwnExecutionTime (mCx, mScript);
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
jsdScript::ClearProfileData() jsdScript::ClearProfileData()
{ {

View File

@ -213,6 +213,27 @@ JSD_GetScriptTotalExecutionTime(JSDContext* jsdc, JSDScript *script)
return jsd_GetScriptTotalExecutionTime(jsdc, script); return jsd_GetScriptTotalExecutionTime(jsdc, script);
} }
JSD_PUBLIC_API(jsdouble)
JSD_GetScriptMinOwnExecutionTime(JSDContext* jsdc, JSDScript *script)
{
JSD_ASSERT_VALID_CONTEXT(jsdc);
return jsd_GetScriptMinOwnExecutionTime(jsdc, script);
}
JSD_PUBLIC_API(jsdouble)
JSD_GetScriptMaxOwnExecutionTime(JSDContext* jsdc, JSDScript *script)
{
JSD_ASSERT_VALID_CONTEXT(jsdc);
return jsd_GetScriptMaxOwnExecutionTime(jsdc, script);
}
JSD_PUBLIC_API(jsdouble)
JSD_GetScriptTotalOwnExecutionTime(JSDContext* jsdc, JSDScript *script)
{
JSD_ASSERT_VALID_CONTEXT(jsdc);
return jsd_GetScriptTotalOwnExecutionTime(jsdc, script);
}
JSD_PUBLIC_API(void) JSD_PUBLIC_API(void)
JSD_ClearScriptProfileData(JSDContext* jsdc, JSDScript *script) JSD_ClearScriptProfileData(JSDContext* jsdc, JSDScript *script)
{ {

View File

@ -327,6 +327,27 @@ JSD_GetScriptMaxExecutionTime(JSDContext* jsdc, JSDScript *script);
extern JSD_PUBLIC_API(jsdouble) extern JSD_PUBLIC_API(jsdouble)
JSD_GetScriptTotalExecutionTime(JSDContext* jsdc, JSDScript *script); JSD_GetScriptTotalExecutionTime(JSDContext* jsdc, JSDScript *script);
/*
* Get the shortest execution time recorded, excluding time spent in called
* functions.
*/
extern JSD_PUBLIC_API(jsdouble)
JSD_GetScriptMinOwnExecutionTime(JSDContext* jsdc, JSDScript *script);
/*
* Get the longest execution time recorded, excluding time spent in called
* functions.
*/
extern JSD_PUBLIC_API(jsdouble)
JSD_GetScriptMaxOwnExecutionTime(JSDContext* jsdc, JSDScript *script);
/*
* Get the total amount of time spent in this script, excluding time spent
* in called functions.
*/
extern JSD_PUBLIC_API(jsdouble)
JSD_GetScriptTotalOwnExecutionTime(JSDContext* jsdc, JSDScript *script);
/* /*
* Clear profile data for this script. * Clear profile data for this script.
*/ */