Have the categories become context aware.
Each context will naturally have it's own set of category runs.
This commit is contained in:
blythe%netscape.com 2002-05-13 01:48:30 +00:00
Родитель 1eb068c665
Коммит bfacfda1cf
3 изменённых файлов: 121 добавлений и 57 удалений

Просмотреть файл

@ -207,6 +207,14 @@ STCategoryNode* NewCategoryNode(const char* catName, STCategoryNode* parent, STG
node = (STCategoryNode *) calloc(1, sizeof(STCategoryNode));
if (!node)
return NULL;
node->runs = (STRun**)calloc(g->mCommandLineOptions.mContexts, sizeof(STRun*));
if(NULL == node->runs)
{
free(node);
return NULL;
}
node->categoryName = catName;
/* Set parent of child */
@ -508,7 +516,7 @@ STCategoryNode* matchAllocation(STGlobals* g, STAllocation* aAllocation)
** The root of the tree is in the globls as the tree is dependent on the
** category file (options) rather than the run.
*/
int categorizeAllocation(STOptions* inOptions, STAllocation* aAllocation, STGlobals* g)
int categorizeAllocation(STOptions* inOptions, STContext* inContext, STAllocation* aAllocation, STGlobals* g)
{
/* Run through the rules in order to see if this allcation matches
** any of them.
@ -525,14 +533,14 @@ int categorizeAllocation(STOptions* inOptions, STAllocation* aAllocation, STGlob
}
/* Create run for node if not already */
if (!node->run)
if (!node->runs[inContext->mIndex])
{
/*
** Create run with positive timestamp as we can harvest it later
** for callsite details summarization
*/
node->run = createRun(PR_IntervalNow());
if (!node->run)
node->runs[inContext->mIndex] = createRun(PR_IntervalNow());
if (!node->runs[inContext->mIndex])
{
REPORT_ERROR(__LINE__, categorizeAllocation_No_Memory);
return -1;
@ -540,27 +548,27 @@ int categorizeAllocation(STOptions* inOptions, STAllocation* aAllocation, STGlob
}
/* Add allocation into node. We expand the table of allocations in steps */
if (node->run->mAllocationCount % ST_ALLOC_STEP == 0)
if (node->runs[inContext->mIndex]->mAllocationCount % ST_ALLOC_STEP == 0)
{
/* Need more space */
STAllocation** allocs;
allocs = (STAllocation**) realloc(node->run->mAllocations,
(node->run->mAllocationCount + ST_ALLOC_STEP) * sizeof(STAllocation*));
allocs = (STAllocation**) realloc(node->runs[inContext->mIndex]->mAllocations,
(node->runs[inContext->mIndex]->mAllocationCount + ST_ALLOC_STEP) * sizeof(STAllocation*));
if (!allocs)
{
REPORT_ERROR(__LINE__, categorizeAllocation_No_Memory);
return -1;
}
node->run->mAllocations = allocs;
node->runs[inContext->mIndex]->mAllocations = allocs;
}
node->run->mAllocations[node->run->mAllocationCount++] = aAllocation;
node->runs[inContext->mIndex]->mAllocations[node->runs[inContext->mIndex]->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(inOptions, node->run, aAllocation, PR_FALSE);
recalculateAllocationCost(inOptions, node->runs[inContext->mIndex], aAllocation, PR_FALSE);
/* Propogate upwards the statistics */
/* XXX */
@ -570,20 +578,42 @@ int categorizeAllocation(STOptions* inOptions, STAllocation* aAllocation, STGlob
return 0;
}
typedef PRBool STCategoryNodeProcessor(STRequest* inRequest, STOptions* inOptions, void* clientData, STCategoryNode* node);
typedef PRBool STCategoryNodeProcessor(STRequest* inRequest, STOptions* inOptions, STContext* inContext, void* clientData, STCategoryNode* node);
PRBool freeNodeRunProcessor(STRequest* inRequest, STOptions* inOptions, void* clientData, STCategoryNode* node)
PRBool freeNodeRunProcessor(STRequest* inRequest, STOptions* inOptions, STContext* inContext, void* clientData, STCategoryNode* node)
{
if (node->run)
if (node->runs && node->runs[inContext->mIndex])
{
freeRun(node->run);
node->run = NULL;
freeRun(node->runs[inContext->mIndex]);
node->runs[inContext->mIndex] = NULL;
}
return PR_TRUE;
}
PRBool freeNodeRunsProcessor(STRequest* inRequest, STOptions* inOptions, STContext* inContext, void* clientData, STCategoryNode* node)
{
if (node->runs)
{
PRUint32 loop = 0;
for(loop = 0; loop < globals.mCommandLineOptions.mContexts; loop++)
{
if (node->runs[loop])
{
freeRun(node->runs[loop]);
node->runs[loop] = NULL;
}
}
free(node->runs);
node->runs = NULL;
}
return PR_TRUE;
}
#if defined(DEBUG_dp)
PRBool printNodeProcessor(STRequest* inRequest, STOptions* inOptions, void* clientData, STCategoryNode* node)
PRBool printNodeProcessor(STRequest* inRequest, STOptions* inOptions, STContext* inContext, void* clientData, STCategoryNode* node)
{
STCategoryNode* root = (STCategoryNode*) clientData;
fprintf(stderr, "%-25s [ %9s size", node->categoryName,
@ -597,6 +627,12 @@ PRBool printNodeProcessor(STRequest* inRequest, STOptions* inOptions, void* clie
#endif
typedef struct __struct_optcon {
STOptions* mOptions;
STContext* mContext;
}
optcon;
/*
** compareNode
**
@ -608,9 +644,9 @@ int compareNode(const void* aNode1, const void* aNode2, void* aContext)
int retval = 0;
STCategoryNode* node1, * node2;
PRUint32 a, b;
STOptions* inOptions = (STOptions*)aContext;
optcon *oc = (optcon*)aContext;
if (!aNode1 || !aNode2 || !inOptions)
if (!aNode1 || !aNode2 || !oc->mOptions || !oc->mContext)
return 0;
node1 = *((STCategoryNode **) aNode1);
@ -618,16 +654,16 @@ int compareNode(const void* aNode1, const void* aNode2, void* aContext)
if (node1 && node2)
{
if (inOptions->mOrderBy == ST_COUNT)
if (oc->mOptions->mOrderBy == ST_COUNT)
{
a = (node1->run) ? node1->run->mStats.mCompositeCount : 0;
b = (node2->run) ? node2->run->mStats.mCompositeCount : 0;
a = (node1->runs[oc->mContext->mIndex]) ? node1->runs[oc->mContext->mIndex]->mStats.mCompositeCount : 0;
b = (node2->runs[oc->mContext->mIndex]) ? node2->runs[oc->mContext->mIndex]->mStats.mCompositeCount : 0;
}
else
{
/* Default is by size */
a = (node1->run) ? node1->run->mStats.mSize : 0;
b = (node2->run) ? node2->run->mStats.mSize : 0;
a = (node1->runs[oc->mContext->mIndex]) ? node1->runs[oc->mContext->mIndex]->mStats.mSize : 0;
b = (node2->runs[oc->mContext->mIndex]) ? node2->runs[oc->mContext->mIndex]->mStats.mSize : 0;
}
if (a < b)
retval = __LINE__;
@ -637,10 +673,17 @@ int compareNode(const void* aNode1, const void* aNode2, void* aContext)
return retval;
}
PRBool sortNodeProcessor(STRequest* inRequest, STOptions* inOptions, void* clientData, STCategoryNode* node)
PRBool sortNodeProcessor(STRequest* inRequest, STOptions* inOptions, STContext* inContext, void* clientData, STCategoryNode* node)
{
if (node->nchildren)
NS_QuickSort(node->children, node->nchildren, sizeof(STCategoryNode *), compareNode, inOptions);
{
optcon context;
context.mOptions = inOptions;
context.mContext = inContext;
NS_QuickSort(node->children, node->nchildren, sizeof(STCategoryNode *), compareNode, &context);
}
return PR_TRUE;
}
@ -655,7 +698,7 @@ PRBool sortNodeProcessor(STRequest* inRequest, STOptions* inOptions, void* clien
*/
#define MODINC(n, mod) ((n+1) % mod)
void walkTree(STCategoryNode* root, STCategoryNodeProcessor func, STRequest* inRequest, STOptions* inOptions, void *clientData, int maxdepth)
void walkTree(STCategoryNode* root, STCategoryNodeProcessor func, STRequest* inRequest, STOptions* inOptions, STContext* inContext, void *clientData, int maxdepth)
{
STCategoryNode* nodes[1024], *node;
PRUint32 begin, end, i;
@ -668,7 +711,7 @@ void walkTree(STCategoryNode* root, STCategoryNodeProcessor func, STRequest* inR
while (begin != end)
{
node = nodes[begin];
ret = (*func)(inRequest, inOptions, clientData, node);
ret = (*func)(inRequest, inOptions, inContext, clientData, node);
if (ret == PR_FALSE)
{
/* Abort */
@ -713,9 +756,9 @@ int freeRule(STCategoryRule* rule)
return 0;
}
void freeNodeRun(STCategoryNode* root)
void freeNodeRuns(STCategoryNode* root)
{
walkTree(root, freeNodeRunProcessor, NULL, NULL, NULL, 0);
walkTree(root, freeNodeRunsProcessor, NULL, NULL, NULL, NULL, 0);
}
void freeNodeMap(STGlobals* g)
@ -738,7 +781,7 @@ int freeCategories(STGlobals* g)
/*
** walk the tree and free runs held in nodes
*/
freeNodeRun(&g->mCategoryRoot);
freeNodeRuns(&g->mCategoryRoot);
/*
** delete nodemap. This is the where nodes get deleted.
@ -764,7 +807,7 @@ int freeCategories(STGlobals* g)
** categorize all the allocations of the run using the rules into
** a tree rooted at globls.mCategoryRoot
*/
int categorizeRun(STOptions* inOptions, const STRun* aRun, STGlobals* g)
int categorizeRun(STOptions* inOptions, STContext* inContext, const STRun* aRun, STGlobals* g)
{
PRUint32 i;
#if defined(DEBUG_dp)
@ -775,20 +818,20 @@ int categorizeRun(STOptions* inOptions, const STRun* aRun, STGlobals* g)
/*
** First, cleanup our tree
*/
walkTree(&g->mCategoryRoot, freeNodeRunProcessor, NULL, inOptions, NULL, 0);
walkTree(&g->mCategoryRoot, freeNodeRunProcessor, NULL, inOptions, inContext, NULL, 0);
if (g->mNCategoryMap > 0)
{
for (i = 0; i < aRun->mAllocationCount; i++)
{
categorizeAllocation(inOptions, aRun->mAllocations[i], g);
categorizeAllocation(inOptions, inContext, aRun->mAllocations[i], g);
}
}
/*
** the run is always going to be the one corresponding to the root node
*/
g->mCategoryRoot.run = (STRun *) aRun;
g->mCategoryRoot.runs[inContext->mIndex] = (STRun *) aRun;
g->mCategoryRoot.categoryName = ST_ROOT_CATEGORY_NAME;
#if defined(DEBUG_dp)
@ -802,10 +845,10 @@ int categorizeRun(STOptions* inOptions, const STRun* aRun, STGlobals* g)
/*
** sort the tree based on our sort criterion
*/
walkTree(&g->mCategoryRoot, sortNodeProcessor, NULL, inOptions, NULL, 0);
walkTree(&g->mCategoryRoot, sortNodeProcessor, NULL, inOptions, inContext, NULL, 0);
#if defined(DEBUG_dp)
walkTree(&g->mCategoryRoot, printNodeProcessor, NULL, inOptions, &g->mCategoryRoot, 0);
walkTree(&g->mCategoryRoot, printNodeProcessor, NULL, inOptions, inContext, &g->mCategoryRoot, 0);
#endif
return 0;
@ -818,36 +861,36 @@ int categorizeRun(STOptions* inOptions, const STRun* aRun, STGlobals* g)
** 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(STRequest* inRequest, STOptions* inOptions, void* clientData, STCategoryNode* node)
PRBool displayCategoryNodeProcessor(STRequest* inRequest, STOptions* inOptions, STContext* inContext, void* clientData, STCategoryNode* node)
{
STCategoryNode* root = (STCategoryNode *) clientData;
PRUint32 byteSize = 0, heapCost = 0, count = 0;
double percent = 0;
STOptions customOps;
if (node->run)
if (node->runs[inContext->mIndex])
{
/*
** Byte size
*/
byteSize = node->run->mStats.mSize;
byteSize = node->runs[inContext->mIndex]->mStats.mSize;
/*
** Composite count
*/
count = node->run->mStats.mCompositeCount;
count = node->runs[inContext->mIndex]->mStats.mCompositeCount;
/*
** Heap operation cost
**/
heapCost = node->run->mStats.mHeapRuntimeCost;
heapCost = node->runs[inContext->mIndex]->mStats.mHeapRuntimeCost;
/*
** % of total size
*/
if (root->run)
if (root->runs[inContext->mIndex])
{
percent = ((double) byteSize) / root->run->mStats.mSize * 100;
percent = ((double) byteSize) / root->runs[inContext->mIndex]->mStats.mSize * 100;
}
}
@ -887,7 +930,7 @@ int displayCategoryReport(STRequest* inRequest, STCategoryNode *root, int depth)
" </tr>\n"
);
walkTree(root, displayCategoryNodeProcessor, inRequest, &inRequest->mOptions, root, depth);
walkTree(root, displayCategoryNodeProcessor, inRequest, &inRequest->mOptions, inRequest->mContext, root, depth);
PR_fprintf(inRequest->mFD, "</table>\n");

Просмотреть файл

@ -1283,11 +1283,11 @@ void freeRun(STRun* aRun)
** Returns NULL on failure.
** Must call freeRun() with the new STRun.
*/
STRun* createRunFromGlobal(STOptions* inOptions)
STRun* createRunFromGlobal(STOptions* inOptions, STContext* inContext)
{
STRun* retval = NULL;
if(NULL != inOptions)
if(NULL != inOptions && NULL != inContext)
{
/*
** We stamp the run.
@ -1327,7 +1327,7 @@ STRun* createRunFromGlobal(STOptions* inOptions)
/*
** Categorize the run.
*/
failure = categorizeRun(inOptions, retval, &globals);
failure = categorizeRun(inOptions, inContext, retval, &globals);
if (0 != failure)
{
REPORT_ERROR(__LINE__, categorizeRun);
@ -1341,9 +1341,9 @@ STRun* createRunFromGlobal(STOptions* inOptions)
if (node)
{
/* Recalculate cost of run */
recalculateRunCost(inOptions, node->run);
recalculateRunCost(inOptions, node->runs[inContext->mIndex]);
retval = node->run;
retval = node->runs[inContext->mIndex];
}
}
}
@ -4915,7 +4915,7 @@ STContext* contextLookup(STOptions* inOptions)
{
unlock = PR_TRUE;
retval->mSortedRun = createRunFromGlobal(&inCache->mItems[retval->mIndex].mOptions);
retval->mSortedRun = createRunFromGlobal(&inCache->mItems[retval->mIndex].mOptions, &inCache->mItems[retval->mIndex].mContext);
}
/*
@ -4936,8 +4936,8 @@ STContext* contextLookup(STOptions* inOptions)
if(node)
{
/* Recalculate cost of run */
recalculateRunCost(&inCache->mItems[retval->mIndex].mOptions, node->run);
retval->mSortedRun = node->run;
recalculateRunCost(&inCache->mItems[retval->mIndex].mOptions, node->runs[retval->mIndex]);
retval->mSortedRun = node->runs[retval->mIndex];
}
#if ST_WANT_GRAPHS
@ -5486,7 +5486,7 @@ void handleClient(void* inArg)
** mime type, otherwise, say it is text/html.
*/
PR_fprintf(aFD, "HTTP/1.1 200 OK%s", crlf);
PR_fprintf(aFD, "Server: %s%s", "$Id: spacetrace.c,v 1.34 2002-05-13 00:01:15 blythe%netscape.com Exp $", crlf);
PR_fprintf(aFD, "Server: %s%s", "$Id: spacetrace.c,v 1.35 2002-05-13 01:48:29 blythe%netscape.com Exp $", crlf);
PR_fprintf(aFD, "Content-type: ");
if(NULL != strstr(start, ".png"))
{
@ -6057,6 +6057,16 @@ int main(int aArgCount, char** aArgArray)
REPORT_ERROR(__LINE__, initCaches);
}
/*
** Small category code init.
*/
globals.mCategoryRoot.runs = (STRun**)calloc(globals.mCommandLineOptions.mContexts, sizeof(STRun*));
if(NULL == globals.mCategoryRoot.runs)
{
retval = __LINE__;
REPORT_ERROR(__LINE__, calloc);
}
/*
** Show help on usage if need be.
*/
@ -6095,6 +6105,15 @@ int main(int aArgCount, char** aArgArray)
** All threads are joined/done by this line.
*/
/*
** Category root has a small modification to clear up.
*/
if(NULL != globals.mCategoryRoot.runs)
{
free(globals.mCategoryRoot.runs);
globals.mCategoryRoot.runs = NULL;
}
/*
** Blow away our caches.
*/

Просмотреть файл

@ -375,9 +375,12 @@ struct __struct_STCategoryNode
PRUint32 nchildren;
/*
** The Run. Valid for both leaf and parent nodes.
** The Run(s). Valid for both leaf and parent nodes.
** One run per --Context to handle multiple data sets.
** The relevant index for the particular request will be
** mIndex stored by the mContext of the request.
*/
STRun *run;
STRun **runs;
};
@ -400,7 +403,6 @@ struct __struct_STCategoryRule
** The node this should be categorized into
*/
STCategoryNode* node;
};
@ -688,7 +690,7 @@ typedef struct __struct_STGlobals
extern STRun* createRun(PRUint32 aStamp);
extern void freeRun(STRun* aRun);
extern int initCategories(STGlobals* g);
extern int categorizeRun(STOptions* inOptions, const STRun* aRun, STGlobals* g);
extern int categorizeRun(STOptions* inOptions, STContext* inContext, const STRun* aRun, STGlobals* g);
extern STCategoryNode* findCategoryNode(const char *catName, STGlobals *g);
extern int freeCategories(STGlobals* g);
extern int displayCategoryReport(STRequest* inRequest, STCategoryNode *root, int depth);