mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-27 12:50:09 +00:00
Categories report
This commit is contained in:
parent
10eb92bad0
commit
9d213f1c92
@ -156,6 +156,11 @@ STCategoryNode* findCategoryNode(const char *catName, STGlobals *g)
|
||||
if (!strcmp(g->mCategoryMap[i]->categoryName, catName))
|
||||
return g->mCategoryMap[i]->node;
|
||||
}
|
||||
|
||||
/* Check if we are looking for the root node */
|
||||
if (!strcmp(catName, ST_ROOT_CATEGORY_NAME))
|
||||
return &g->mCategoryRoot;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -534,6 +539,13 @@ int categorizeAllocation(STAllocation* aAllocation, STGlobals* g)
|
||||
}
|
||||
node->run->mAllocations[node->run->mAllocationCount++] = aAllocation;
|
||||
|
||||
/*
|
||||
** Make sure run's stats are calculated. We dont go update the parents of allocation
|
||||
** at this time. That will happen when we focus on this category. This updating of
|
||||
** stats will provide us fast categoryreports.
|
||||
*/
|
||||
recalculateAllocationCost(node->run, aAllocation, PR_FALSE);
|
||||
|
||||
/* Propogate upwards the statistics */
|
||||
/* XXX */
|
||||
#if defined(DEBUG_dp) && 0
|
||||
@ -569,18 +581,22 @@ PRBool printNodeProcessor(void* clientData, STCategoryNode* node)
|
||||
/*
|
||||
** walkTree
|
||||
**
|
||||
** General purpose tree walker. Issues callback for each node
|
||||
** General purpose tree walker. Issues callback for each node.
|
||||
** If 'maxdepth' > 0, then stops after processing that depth. Root is
|
||||
** depth 0, the nodes below it are depth 1 etc...
|
||||
*/
|
||||
#define MODINC(n, mod) ((n+1) % mod)
|
||||
|
||||
void walkTree(STCategoryNode* root, STCategoryNodeProcessor func, void *clientData)
|
||||
void walkTree(STCategoryNode* root, STCategoryNodeProcessor func, void *clientData, int maxdepth)
|
||||
{
|
||||
STCategoryNode* nodes[1024], *node;
|
||||
PRUint32 begin, end, i;
|
||||
int ret = 0;
|
||||
int curdepth = 0, ncurdepth = 0;
|
||||
|
||||
nodes[0] = root;
|
||||
begin = 0; end = 1;
|
||||
ncurdepth = 1;
|
||||
while (begin != end)
|
||||
{
|
||||
node = nodes[begin];
|
||||
@ -596,6 +612,22 @@ void walkTree(STCategoryNode* root, STCategoryNodeProcessor func, void *clientDa
|
||||
nodes[end] = node->children[i];
|
||||
end = MODINC(end, 1024);
|
||||
}
|
||||
/* Depth tracking. Do it only if walkTree is contrained by a maxdepth */
|
||||
if (maxdepth > 0 && --ncurdepth == 0)
|
||||
{
|
||||
/*
|
||||
** No more children in current depth. The rest of the nodes
|
||||
** we have in our list should be nodes in the depth below us.
|
||||
*/
|
||||
ncurdepth = (begin < end) ? (end - begin) : (1024 - begin + end);
|
||||
if (++curdepth > maxdepth)
|
||||
{
|
||||
/*
|
||||
** Gone too deep. Stop.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -615,7 +647,7 @@ int freeRule(STCategoryRule* rule)
|
||||
|
||||
void freeNodeRun(STCategoryNode* root)
|
||||
{
|
||||
walkTree(root, freeNodeRunProcessor, NULL);
|
||||
walkTree(root, freeNodeRunProcessor, NULL, 0);
|
||||
}
|
||||
|
||||
void freeNodeMap(STGlobals* g)
|
||||
@ -675,7 +707,7 @@ int categorizeRun(const STRun* aRun, STGlobals* g)
|
||||
/*
|
||||
** First, cleanup our tree
|
||||
*/
|
||||
walkTree(&g->mCategoryRoot, freeNodeRunProcessor, NULL);
|
||||
walkTree(&g->mCategoryRoot, freeNodeRunProcessor, NULL, 0);
|
||||
|
||||
if (g->mNCategoryMap > 0)
|
||||
{
|
||||
@ -692,7 +724,7 @@ int categorizeRun(const STRun* aRun, STGlobals* g)
|
||||
g->mCategoryRoot.categoryName = ST_ROOT_CATEGORY_NAME;
|
||||
|
||||
#if defined(DEBUG_dp)
|
||||
walkTree(&g->mCategoryRoot, printNodeProcessor, NULL);
|
||||
walkTree(&g->mCategoryRoot, printNodeProcessor, NULL, 0);
|
||||
fprintf(stderr, "DEBUG: categorizing ends: %dms [%d rules, %d allocations]\n",
|
||||
PR_IntervalToMilliseconds(PR_IntervalNow() - start), g->mNRules, aRun->mAllocationCount);
|
||||
#endif
|
||||
@ -700,3 +732,82 @@ int categorizeRun(const STRun* aRun, STGlobals* g)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** displayCategoryReport
|
||||
**
|
||||
** Generate the category report - a list of all categories and details about each
|
||||
** depth parameter controls how deep we traverse the category tree.
|
||||
*/
|
||||
PRBool displayCategoryNodeProcessor(void* clientData, STCategoryNode* node)
|
||||
{
|
||||
STCategoryNode* root = (STCategoryNode *) clientData;
|
||||
PRUint32 byteSize = 0, heapCost = 0, count = 0;
|
||||
double percent = 0;
|
||||
char buf[256];
|
||||
|
||||
if (node->run)
|
||||
{
|
||||
/*
|
||||
** Byte size
|
||||
*/
|
||||
byteSize = node->run->mStats.mSize;
|
||||
|
||||
/*
|
||||
** Composite count
|
||||
*/
|
||||
count = node->run->mStats.mCompositeCount;
|
||||
|
||||
/*
|
||||
** Heap operation cost
|
||||
**/
|
||||
heapCost = node->run->mStats.mHeapRuntimeCost;
|
||||
|
||||
/*
|
||||
** % of total size
|
||||
*/
|
||||
if (root->run)
|
||||
{
|
||||
percent = ((double) byteSize) / root->run->mStats.mSize * 100;
|
||||
}
|
||||
}
|
||||
|
||||
PR_fprintf(globals.mRequest.mFD,
|
||||
" <tr>\n"
|
||||
" <td>");
|
||||
/* a link to topcallsites report with focus on category */
|
||||
PR_snprintf(buf, sizeof(buf), "top_callsites.html?mCategory=%s", node->categoryName);
|
||||
htmlAnchor(buf, node->categoryName, NULL);
|
||||
PR_fprintf(globals.mRequest.mFD,
|
||||
"</td>\n"
|
||||
" <td align=right>%u</td>\n"
|
||||
" <td align=right>%4.1f%%</td>\n"
|
||||
" <td align=right>%u</td>\n"
|
||||
" <td align=right>" ST_MICROVAL_FORMAT "</td>\n"
|
||||
" </tr>\n",
|
||||
byteSize, percent, count,
|
||||
ST_MICROVAL_PRINTABLE(heapCost));
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
||||
int displayCategoryReport(STCategoryNode *root, int depth)
|
||||
{
|
||||
PR_fprintf(globals.mRequest.mFD,
|
||||
"<table border=1>\n"
|
||||
" <tr>\n"
|
||||
" <th>Category</th>\n"
|
||||
" <th>Composite Byte Size</th>\n"
|
||||
" <th>%% of Total Size</th>\n"
|
||||
" <th>Heap Object Count</th>\n"
|
||||
" <th>Composite Heap Operations Seconds</th>\n"
|
||||
" </tr>\n"
|
||||
);
|
||||
|
||||
walkTree(root, displayCategoryNodeProcessor, root, depth);
|
||||
|
||||
PR_fprintf(globals.mRequest.mFD, "</table>\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1232,7 +1232,7 @@ PRUint32 byteSize(STAllocation* aAlloc)
|
||||
** Given an allocation, does a recalculation of Cost - weight, heapcount etc.
|
||||
** and does the right thing to propogate the cost upwards.
|
||||
*/
|
||||
int recalculateAllocationCost(STRun* aRun, STAllocation* aAllocation)
|
||||
int recalculateAllocationCost(STRun* aRun, STAllocation* aAllocation, PRBool updateParent)
|
||||
{
|
||||
/*
|
||||
** Now, see if they desire a callsite update.
|
||||
@ -1270,7 +1270,7 @@ int recalculateAllocationCost(STRun* aRun, STAllocation* aAllocation)
|
||||
** This has positive effect of not updating realloc callsites
|
||||
** with the same data over and over again.
|
||||
*/
|
||||
if(0 < aAllocation->mEventCount)
|
||||
if(updateParent && 0 < aAllocation->mEventCount)
|
||||
{
|
||||
tmcallsite* callsite = aAllocation->mEvents[0].mCallsite;
|
||||
STRun* callsiteRun = NULL;
|
||||
@ -1381,7 +1381,7 @@ int appendAllocation(STRun* aRun, STAllocation* aAllocation)
|
||||
/*
|
||||
** update allocation cost
|
||||
*/
|
||||
recalculateAllocationCost(aRun, aAllocation);
|
||||
recalculateAllocationCost(aRun, aAllocation, PR_TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1662,7 +1662,7 @@ int recalculateRunCost(STRun* aRun)
|
||||
current = aRun->mAllocations[traverse];
|
||||
if(NULL != current)
|
||||
{
|
||||
recalculateAllocationCost(aRun, current);
|
||||
recalculateAllocationCost(aRun, current, PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5328,6 +5328,9 @@ int displayIndex(void)
|
||||
PR_fprintf(globals.mRequest.mFD, "\n<li>");
|
||||
htmlAnchor("root_callsites.html", "Root Callsites", NULL);
|
||||
|
||||
PR_fprintf(globals.mRequest.mFD, "\n<li>");
|
||||
htmlAnchor("categories_summary.html", "Categories Report", NULL);
|
||||
|
||||
PR_fprintf(globals.mRequest.mFD, "\n<li>");
|
||||
htmlAnchor("top_callsites.html", "Top Callsites Report", NULL);
|
||||
|
||||
@ -5436,6 +5439,35 @@ int handleRequest(tmreader* aTMR, PRFileDesc* aFD, const char* aFileName, const
|
||||
tmcallsite** array = NULL;
|
||||
PRUint32 arrayCount = 0;
|
||||
|
||||
/*
|
||||
** We can get an argument to focus on a category. Take care of it.
|
||||
*/
|
||||
|
||||
if(globals.mRequest.mGetData && *globals.mRequest.mGetData)
|
||||
{
|
||||
char* categoryName = NULL;
|
||||
int getRes = getDataString(globals.mRequest.mGetData, "mCategory", &categoryName, NULL);
|
||||
STCategoryNode* node;
|
||||
if (categoryName && *categoryName &&
|
||||
strcmp(categoryName, globals.mOptions.mCategoryName) &&
|
||||
(node = findCategoryNode(categoryName, &globals)))
|
||||
{
|
||||
/*
|
||||
** category has changed. Refocus.
|
||||
*/
|
||||
recalculateRunCost(node->run);
|
||||
|
||||
globals.mCache.mSortedRun = node->run;
|
||||
if (globals.mOptions.mCategoryName)
|
||||
free(globals.mOptions.mCategoryName);
|
||||
globals.mOptions.mCategoryName = categoryName;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Display header after we figure out if we are going to focus
|
||||
** on a category.
|
||||
*/
|
||||
htmlHeader("SpaceTrace Top Callsites Report");
|
||||
|
||||
if(0 < globals.mCache.mSortedRun->mAllocationCount)
|
||||
@ -5687,6 +5719,21 @@ int handleRequest(tmreader* aTMR, PRFileDesc* aFD, const char* aFileName, const
|
||||
htmlFooter();
|
||||
}
|
||||
#endif /* WANT_QUIT */
|
||||
else if(0 == strcmp("categories_summary.html", aFileName))
|
||||
{
|
||||
int displayRes = 0;
|
||||
|
||||
htmlHeader("Category Report");
|
||||
|
||||
displayRes = displayCategoryReport(&globals.mCategoryRoot, 1);
|
||||
if(0 != displayRes)
|
||||
{
|
||||
retval = __LINE__;
|
||||
REPORT_ERROR(__LINE__, displayMemoryLeaks);
|
||||
}
|
||||
|
||||
htmlFooter();
|
||||
}
|
||||
else
|
||||
{
|
||||
htmlNotFound();
|
||||
|
@ -344,7 +344,7 @@ struct __struct_STCategoryNode
|
||||
PRUint32 nchildren;
|
||||
|
||||
/*
|
||||
** For leaf nodes, the Run
|
||||
** The Run. Valid for both leaf and parent nodes.
|
||||
*/
|
||||
STRun *run;
|
||||
};
|
||||
@ -653,9 +653,17 @@ extern int initCategories(STGlobals* g);
|
||||
extern int categorizeRun(const STRun* aRun, STGlobals* g);
|
||||
extern STCategoryNode* findCategoryNode(const char *catName, STGlobals *g);
|
||||
extern int freeCategories(STGlobals* g);
|
||||
#endif /* spacetrace_h__ */
|
||||
extern int displayCategoryReport(STCategoryNode *root, int depth);
|
||||
|
||||
extern int recalculateAllocationCost(STRun* aRun, STAllocation* aAllocation, PRBool updateParent);
|
||||
extern void htmlHeader(const char* aTitle);
|
||||
extern void htmlFooter(void);
|
||||
extern void htmlAnchor(const char* aHref, const char* aText, const char* aTarget);
|
||||
|
||||
|
||||
/*
|
||||
** shared globals
|
||||
*/
|
||||
extern STGlobals globals;
|
||||
|
||||
#endif /* spacetrace_h__ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user