зеркало из https://github.com/mozilla/gecko-dev.git
Add possibly-too-verbose NS_TraceMallocDumpAllocations and its JS window-level function, for leak and bloat analysis.
This commit is contained in:
Родитель
8507f2d98b
Коммит
5387c4e16b
|
@ -1088,14 +1088,32 @@ TraceMallocLogTimestamp(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, j
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
TraceMallocDumpAllocations(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
JSString *str;
|
||||
const char *pathname;
|
||||
|
||||
str = JS_ValueToString(cx, argv[0]);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
pathname = JS_GetStringBytes(str);
|
||||
if (NS_TraceMallocDumpAllocations(pathname) < 0) {
|
||||
JS_ReportError(cx, "can't dump to %s: %s", pathname, strerror(errno));
|
||||
return JS_FALSE;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSFunctionSpec TraceMallocFunctions[] = {
|
||||
{"TraceMallocDisable", TraceMallocDisable, 0, 0, 0},
|
||||
{"TraceMallocEnable", TraceMallocEnable, 0, 0, 0},
|
||||
{"TraceMallocOpenLogFile", TraceMallocOpenLogFile, 1, 0, 0},
|
||||
{"TraceMallocChangeLogFD", TraceMallocChangeLogFD, 1, 0, 0},
|
||||
{"TraceMallocCloseLogFD", TraceMallocCloseLogFD, 1, 0, 0},
|
||||
{"TraceMallocLogTimestamp", TraceMallocLogTimestamp, 1, 0, 0},
|
||||
{NULL, NULL, 0, 0, 0}
|
||||
{"TraceMallocDisable", TraceMallocDisable, 0, 0, 0},
|
||||
{"TraceMallocEnable", TraceMallocEnable, 0, 0, 0},
|
||||
{"TraceMallocOpenLogFile", TraceMallocOpenLogFile, 1, 0, 0},
|
||||
{"TraceMallocChangeLogFD", TraceMallocChangeLogFD, 1, 0, 0},
|
||||
{"TraceMallocCloseLogFD", TraceMallocCloseLogFD, 1, 0, 0},
|
||||
{"TraceMallocLogTimestamp", TraceMallocLogTimestamp, 1, 0, 0},
|
||||
{"TraceMallocDumpAllocations", TraceMallocDumpAllocations, 1, 0, 0},
|
||||
{NULL, NULL, 0, 0, 0}
|
||||
};
|
||||
|
||||
#endif /* NS_TRACE_MALLOC */
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
*/
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <setjmp.h>
|
||||
|
@ -374,6 +375,7 @@ struct callsite {
|
|||
uint32 serial;
|
||||
lfd_set lfdset;
|
||||
char *name;
|
||||
int offset;
|
||||
callsite *parent;
|
||||
callsite *siblings;
|
||||
callsite *kids;
|
||||
|
@ -387,7 +389,7 @@ static uint32 callsite_serial_generator = 0;
|
|||
static uint32 tmstats_serial_generator = 0;
|
||||
|
||||
/* Root of the tree of callsites, the sum of all (cycle-compressed) stacks. */
|
||||
static callsite calltree_root = {0, 0, LFD_SET_STATIC_INITIALIZER, NULL, NULL, NULL, NULL};
|
||||
static callsite calltree_root = {0, 0, LFD_SET_STATIC_INITIALIZER, NULL, 0, NULL, NULL, NULL};
|
||||
|
||||
/* Basic instrumentation. */
|
||||
static nsTMStats tmstats = NS_TMSTATS_STATIC_INITIALIZER;
|
||||
|
@ -693,6 +695,7 @@ static callsite *calltree(uint32 *bp)
|
|||
site->serial = ++callsite_serial_generator;
|
||||
LFD_ZERO(&site->lfdset);
|
||||
site->name = method;
|
||||
site->offset = offset;
|
||||
site->parent = parent;
|
||||
site->siblings = parent->kids;
|
||||
parent->kids = site;
|
||||
|
@ -1259,4 +1262,40 @@ NS_TraceMallocLogTimestamp(const char *caption)
|
|||
PR_ExitMonitor(tmmon);
|
||||
}
|
||||
|
||||
static PRIntn
|
||||
allocation_enumerator(PLHashEntry *he, PRIntn i, void *arg)
|
||||
{
|
||||
allocation *alloc = (allocation*) he;
|
||||
FILE *ofp = (FILE*) arg;
|
||||
callsite *site = (callsite*) he->value;
|
||||
|
||||
fprintf(ofp, "%8p %9lu ", he->key, (unsigned long) alloc->size);
|
||||
while (site) {
|
||||
if (site->name || site->parent)
|
||||
fprintf(ofp, " %s+%d", site->name, site->offset);
|
||||
site = site->parent;
|
||||
if (site)
|
||||
fputc(';', ofp);
|
||||
}
|
||||
fputc('\n', ofp);
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(int)
|
||||
NS_TraceMallocDumpAllocations(const char *pathname)
|
||||
{
|
||||
FILE *ofp;
|
||||
int rv;
|
||||
|
||||
ofp = fopen(pathname, "w");
|
||||
if (!ofp)
|
||||
return -1;
|
||||
fprintf(ofp, "Address size stack\n");
|
||||
if (allocations)
|
||||
PL_HashTableEnumerateEntries(allocations, allocation_enumerator, ofp);
|
||||
rv = ferror(ofp) ? -1 : 0;
|
||||
fclose(ofp);
|
||||
return rv;
|
||||
}
|
||||
|
||||
#endif /* NS_TRACE_MALLOC */
|
||||
|
|
|
@ -158,6 +158,16 @@ PR_EXTERN(void) NS_TraceMallocCloseLogFD(int fd);
|
|||
*/
|
||||
PR_EXTERN(void) NS_TraceMallocLogTimestamp(const char *caption);
|
||||
|
||||
/**
|
||||
* Dump a human-readable listing of current allocations and their compressed
|
||||
* stack backtraces to the file named by pathname. Beware this file may have
|
||||
* very long lines.
|
||||
*
|
||||
* Return -1 on error with errno set by the system, 0 on success.
|
||||
*/
|
||||
PR_EXTERN(int)
|
||||
NS_TraceMallocDumpAllocations(const char *pathname);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* nsTraceMalloc_h___ */
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
*/
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <setjmp.h>
|
||||
|
@ -374,6 +375,7 @@ struct callsite {
|
|||
uint32 serial;
|
||||
lfd_set lfdset;
|
||||
char *name;
|
||||
int offset;
|
||||
callsite *parent;
|
||||
callsite *siblings;
|
||||
callsite *kids;
|
||||
|
@ -387,7 +389,7 @@ static uint32 callsite_serial_generator = 0;
|
|||
static uint32 tmstats_serial_generator = 0;
|
||||
|
||||
/* Root of the tree of callsites, the sum of all (cycle-compressed) stacks. */
|
||||
static callsite calltree_root = {0, 0, LFD_SET_STATIC_INITIALIZER, NULL, NULL, NULL, NULL};
|
||||
static callsite calltree_root = {0, 0, LFD_SET_STATIC_INITIALIZER, NULL, 0, NULL, NULL, NULL};
|
||||
|
||||
/* Basic instrumentation. */
|
||||
static nsTMStats tmstats = NS_TMSTATS_STATIC_INITIALIZER;
|
||||
|
@ -693,6 +695,7 @@ static callsite *calltree(uint32 *bp)
|
|||
site->serial = ++callsite_serial_generator;
|
||||
LFD_ZERO(&site->lfdset);
|
||||
site->name = method;
|
||||
site->offset = offset;
|
||||
site->parent = parent;
|
||||
site->siblings = parent->kids;
|
||||
parent->kids = site;
|
||||
|
@ -1259,4 +1262,40 @@ NS_TraceMallocLogTimestamp(const char *caption)
|
|||
PR_ExitMonitor(tmmon);
|
||||
}
|
||||
|
||||
static PRIntn
|
||||
allocation_enumerator(PLHashEntry *he, PRIntn i, void *arg)
|
||||
{
|
||||
allocation *alloc = (allocation*) he;
|
||||
FILE *ofp = (FILE*) arg;
|
||||
callsite *site = (callsite*) he->value;
|
||||
|
||||
fprintf(ofp, "%8p %9lu ", he->key, (unsigned long) alloc->size);
|
||||
while (site) {
|
||||
if (site->name || site->parent)
|
||||
fprintf(ofp, " %s+%d", site->name, site->offset);
|
||||
site = site->parent;
|
||||
if (site)
|
||||
fputc(';', ofp);
|
||||
}
|
||||
fputc('\n', ofp);
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(int)
|
||||
NS_TraceMallocDumpAllocations(const char *pathname)
|
||||
{
|
||||
FILE *ofp;
|
||||
int rv;
|
||||
|
||||
ofp = fopen(pathname, "w");
|
||||
if (!ofp)
|
||||
return -1;
|
||||
fprintf(ofp, "Address size stack\n");
|
||||
if (allocations)
|
||||
PL_HashTableEnumerateEntries(allocations, allocation_enumerator, ofp);
|
||||
rv = ferror(ofp) ? -1 : 0;
|
||||
fclose(ofp);
|
||||
return rv;
|
||||
}
|
||||
|
||||
#endif /* NS_TRACE_MALLOC */
|
||||
|
|
|
@ -158,6 +158,16 @@ PR_EXTERN(void) NS_TraceMallocCloseLogFD(int fd);
|
|||
*/
|
||||
PR_EXTERN(void) NS_TraceMallocLogTimestamp(const char *caption);
|
||||
|
||||
/**
|
||||
* Dump a human-readable listing of current allocations and their compressed
|
||||
* stack backtraces to the file named by pathname. Beware this file may have
|
||||
* very long lines.
|
||||
*
|
||||
* Return -1 on error with errno set by the system, 0 on success.
|
||||
*/
|
||||
PR_EXTERN(int)
|
||||
NS_TraceMallocDumpAllocations(const char *pathname);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* nsTraceMalloc_h___ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче