2000-07-09 12:53:46 +04:00
|
|
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public
|
|
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy of
|
|
|
|
* the License at http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS
|
|
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
|
|
|
* implied. See the License for the specific language governing
|
|
|
|
* rights and limitations under the License.
|
|
|
|
*
|
|
|
|
* The Original Code is tmreader.h/tmreader.c code, released
|
|
|
|
* July 7, 2000.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is Netscape
|
|
|
|
* Communications Corporation. Portions created by Netscape are
|
|
|
|
* Copyright (C) 2000 Netscape Communications Corporation. All
|
|
|
|
* Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
* Brendan Eich, 7-July-2000
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the
|
|
|
|
* terms of the GNU Public License (the "GPL"), in which case the
|
|
|
|
* provisions of the GPL are applicable instead of those above.
|
|
|
|
* If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of the GPL and not to allow others to use your
|
|
|
|
* version of this file under the MPL, indicate your decision by
|
|
|
|
* deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this
|
|
|
|
* file under either the MPL or the GPL.
|
|
|
|
*/
|
|
|
|
#ifndef tmreader_h___
|
|
|
|
#define tmreader_h___
|
|
|
|
|
|
|
|
#include "prtypes.h"
|
|
|
|
#include "plhash.h"
|
|
|
|
#include "nsTraceMalloc.h"
|
|
|
|
|
|
|
|
PR_BEGIN_EXTERN_C
|
|
|
|
|
|
|
|
typedef struct tmreader tmreader;
|
|
|
|
typedef struct tmevent tmevent;
|
2000-07-22 00:42:15 +04:00
|
|
|
typedef struct tmcounts tmcounts;
|
- Remove <unistd.h> include from bloatblame, it's no longer needed and the link(2) prototype it drags in was causing warnings whenever I used a local variable named 'link'.
- Use uint32 for all quantities, and double for all differences, so that we can overflow without breaking deltas such as (busy == allocs - frees). This doesn't help sorting, however: if one of the sort keys has overflowed past 0 just a bit, while the other is a very large unsigned number, beware.
- Separate graph link (half an edge, structurally speaking -- no per-edge stats) from graph edge, so that an edge is two links and some stats. This avoids bloat and copying in connect_nodes (which is soon to become generic and move to tmreader.[ch]).
- Factor data structures better: we now have {allocs,frees} x {bytes,calls} x {direct, total}, declaring the second set as struct tmallcounts and the third as tmcounts. So, for example, total number of calls to allocators would be allocs.calls.total; bytes freed directly by a graphnode (library, component, or method) would be frees.bytes.direct.
- Teach tmreader_eventloop about 'F' (TM_EVENT_FREE) events: it now updates the direct free byte and call counts for a method, its component, and its library when it reads the event. Of course, bloatblame ignores this info, because it is concerned only with bloat (total memory allocated).
- Right-align numbers in the first (trace-malloc stats) table.
2000-07-26 04:24:08 +04:00
|
|
|
typedef struct tmallcounts tmallcounts;
|
|
|
|
typedef struct tmgraphlink tmgraphlink;
|
2000-07-09 12:53:46 +04:00
|
|
|
typedef struct tmgraphedge tmgraphedge;
|
|
|
|
typedef struct tmgraphnode tmgraphnode;
|
|
|
|
typedef struct tmcallsite tmcallsite;
|
|
|
|
|
|
|
|
struct tmevent {
|
|
|
|
char type;
|
|
|
|
uint32 serial;
|
|
|
|
union {
|
|
|
|
char *libname;
|
|
|
|
struct {
|
|
|
|
uint32 library;
|
|
|
|
char *name;
|
|
|
|
} method;
|
|
|
|
struct {
|
|
|
|
uint32 parent;
|
|
|
|
uint32 method;
|
|
|
|
uint32 offset;
|
|
|
|
} site;
|
|
|
|
struct {
|
|
|
|
uint32 size;
|
2000-11-22 11:05:05 +03:00
|
|
|
uint32 oldserial;
|
|
|
|
uint32 oldsize;
|
2000-07-09 12:53:46 +04:00
|
|
|
} alloc;
|
|
|
|
struct {
|
|
|
|
nsTMStats tmstats;
|
|
|
|
uint32 calltree_maxkids_parent;
|
|
|
|
uint32 calltree_maxstack_top;
|
|
|
|
} stats;
|
|
|
|
} u;
|
|
|
|
};
|
|
|
|
|
2000-07-22 00:42:15 +04:00
|
|
|
struct tmcounts {
|
- Remove <unistd.h> include from bloatblame, it's no longer needed and the link(2) prototype it drags in was causing warnings whenever I used a local variable named 'link'.
- Use uint32 for all quantities, and double for all differences, so that we can overflow without breaking deltas such as (busy == allocs - frees). This doesn't help sorting, however: if one of the sort keys has overflowed past 0 just a bit, while the other is a very large unsigned number, beware.
- Separate graph link (half an edge, structurally speaking -- no per-edge stats) from graph edge, so that an edge is two links and some stats. This avoids bloat and copying in connect_nodes (which is soon to become generic and move to tmreader.[ch]).
- Factor data structures better: we now have {allocs,frees} x {bytes,calls} x {direct, total}, declaring the second set as struct tmallcounts and the third as tmcounts. So, for example, total number of calls to allocators would be allocs.calls.total; bytes freed directly by a graphnode (library, component, or method) would be frees.bytes.direct.
- Teach tmreader_eventloop about 'F' (TM_EVENT_FREE) events: it now updates the direct free byte and call counts for a method, its component, and its library when it reads the event. Of course, bloatblame ignores this info, because it is concerned only with bloat (total memory allocated).
- Right-align numbers in the first (trace-malloc stats) table.
2000-07-26 04:24:08 +04:00
|
|
|
uint32 direct; /* things allocated by this node's code */
|
|
|
|
uint32 total; /* direct + things from all descendents */
|
|
|
|
};
|
|
|
|
|
|
|
|
struct tmallcounts {
|
|
|
|
tmcounts bytes;
|
|
|
|
tmcounts calls;
|
2000-07-22 00:42:15 +04:00
|
|
|
};
|
2000-07-09 12:53:46 +04:00
|
|
|
|
|
|
|
struct tmgraphnode {
|
|
|
|
PLHashEntry entry; /* key is serial or name, value must be name */
|
- Remove <unistd.h> include from bloatblame, it's no longer needed and the link(2) prototype it drags in was causing warnings whenever I used a local variable named 'link'.
- Use uint32 for all quantities, and double for all differences, so that we can overflow without breaking deltas such as (busy == allocs - frees). This doesn't help sorting, however: if one of the sort keys has overflowed past 0 just a bit, while the other is a very large unsigned number, beware.
- Separate graph link (half an edge, structurally speaking -- no per-edge stats) from graph edge, so that an edge is two links and some stats. This avoids bloat and copying in connect_nodes (which is soon to become generic and move to tmreader.[ch]).
- Factor data structures better: we now have {allocs,frees} x {bytes,calls} x {direct, total}, declaring the second set as struct tmallcounts and the third as tmcounts. So, for example, total number of calls to allocators would be allocs.calls.total; bytes freed directly by a graphnode (library, component, or method) would be frees.bytes.direct.
- Teach tmreader_eventloop about 'F' (TM_EVENT_FREE) events: it now updates the direct free byte and call counts for a method, its component, and its library when it reads the event. Of course, bloatblame ignores this info, because it is concerned only with bloat (total memory allocated).
- Right-align numbers in the first (trace-malloc stats) table.
2000-07-26 04:24:08 +04:00
|
|
|
tmgraphlink *in;
|
|
|
|
tmgraphlink *out;
|
2000-07-09 12:53:46 +04:00
|
|
|
tmgraphnode *up; /* parent in supergraph, e.g., JS for JS_*() */
|
|
|
|
tmgraphnode *down; /* subgraph kids, declining bytes.total order */
|
|
|
|
tmgraphnode *next; /* next kid in supergraph node's down list */
|
|
|
|
int low; /* 0 or lowest current tree walk level */
|
- Remove <unistd.h> include from bloatblame, it's no longer needed and the link(2) prototype it drags in was causing warnings whenever I used a local variable named 'link'.
- Use uint32 for all quantities, and double for all differences, so that we can overflow without breaking deltas such as (busy == allocs - frees). This doesn't help sorting, however: if one of the sort keys has overflowed past 0 just a bit, while the other is a very large unsigned number, beware.
- Separate graph link (half an edge, structurally speaking -- no per-edge stats) from graph edge, so that an edge is two links and some stats. This avoids bloat and copying in connect_nodes (which is soon to become generic and move to tmreader.[ch]).
- Factor data structures better: we now have {allocs,frees} x {bytes,calls} x {direct, total}, declaring the second set as struct tmallcounts and the third as tmcounts. So, for example, total number of calls to allocators would be allocs.calls.total; bytes freed directly by a graphnode (library, component, or method) would be frees.bytes.direct.
- Teach tmreader_eventloop about 'F' (TM_EVENT_FREE) events: it now updates the direct free byte and call counts for a method, its component, and its library when it reads the event. Of course, bloatblame ignores this info, because it is concerned only with bloat (total memory allocated).
- Right-align numbers in the first (trace-malloc stats) table.
2000-07-26 04:24:08 +04:00
|
|
|
tmallcounts allocs;
|
|
|
|
tmallcounts frees;
|
2000-07-09 12:53:46 +04:00
|
|
|
double sqsum; /* sum of squared bytes.direct */
|
|
|
|
int sort; /* sorted index in node table, -1 if no table */
|
|
|
|
};
|
|
|
|
|
|
|
|
#define tmgraphnode_name(node) ((char*) (node)->entry.value)
|
|
|
|
|
|
|
|
#define tmlibrary_serial(lib) ((uint32) (lib)->entry.key)
|
|
|
|
#define tmcomponent_name(comp) ((const char*) (comp)->entry.key)
|
|
|
|
|
- Remove <unistd.h> include from bloatblame, it's no longer needed and the link(2) prototype it drags in was causing warnings whenever I used a local variable named 'link'.
- Use uint32 for all quantities, and double for all differences, so that we can overflow without breaking deltas such as (busy == allocs - frees). This doesn't help sorting, however: if one of the sort keys has overflowed past 0 just a bit, while the other is a very large unsigned number, beware.
- Separate graph link (half an edge, structurally speaking -- no per-edge stats) from graph edge, so that an edge is two links and some stats. This avoids bloat and copying in connect_nodes (which is soon to become generic and move to tmreader.[ch]).
- Factor data structures better: we now have {allocs,frees} x {bytes,calls} x {direct, total}, declaring the second set as struct tmallcounts and the third as tmcounts. So, for example, total number of calls to allocators would be allocs.calls.total; bytes freed directly by a graphnode (library, component, or method) would be frees.bytes.direct.
- Teach tmreader_eventloop about 'F' (TM_EVENT_FREE) events: it now updates the direct free byte and call counts for a method, its component, and its library when it reads the event. Of course, bloatblame ignores this info, because it is concerned only with bloat (total memory allocated).
- Right-align numbers in the first (trace-malloc stats) table.
2000-07-26 04:24:08 +04:00
|
|
|
/* Half a graphedge, not including per-edge allocation stats. */
|
|
|
|
struct tmgraphlink {
|
|
|
|
tmgraphlink *next; /* next fanning out from or into a node */
|
|
|
|
tmgraphnode *node; /* the other node (to if OUT, from if IN) */
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* It's safe to downcast a "from" tmgraphlink (one linked from a node's out
|
|
|
|
* pointer) to tmgraphedge. To go from an "out" (linked via tmgraphedge.from)
|
|
|
|
* or "in" (linked via tmgraphedge.to) list link to its containing edge, use
|
|
|
|
* TM_LINK_TO_EDGE(link, which).
|
|
|
|
*/
|
2000-07-09 12:53:46 +04:00
|
|
|
struct tmgraphedge {
|
- Remove <unistd.h> include from bloatblame, it's no longer needed and the link(2) prototype it drags in was causing warnings whenever I used a local variable named 'link'.
- Use uint32 for all quantities, and double for all differences, so that we can overflow without breaking deltas such as (busy == allocs - frees). This doesn't help sorting, however: if one of the sort keys has overflowed past 0 just a bit, while the other is a very large unsigned number, beware.
- Separate graph link (half an edge, structurally speaking -- no per-edge stats) from graph edge, so that an edge is two links and some stats. This avoids bloat and copying in connect_nodes (which is soon to become generic and move to tmreader.[ch]).
- Factor data structures better: we now have {allocs,frees} x {bytes,calls} x {direct, total}, declaring the second set as struct tmallcounts and the third as tmcounts. So, for example, total number of calls to allocators would be allocs.calls.total; bytes freed directly by a graphnode (library, component, or method) would be frees.bytes.direct.
- Teach tmreader_eventloop about 'F' (TM_EVENT_FREE) events: it now updates the direct free byte and call counts for a method, its component, and its library when it reads the event. Of course, bloatblame ignores this info, because it is concerned only with bloat (total memory allocated).
- Right-align numbers in the first (trace-malloc stats) table.
2000-07-26 04:24:08 +04:00
|
|
|
tmgraphlink links[2];
|
|
|
|
tmallcounts allocs;
|
|
|
|
tmallcounts frees;
|
2000-07-09 12:53:46 +04:00
|
|
|
};
|
|
|
|
|
- Remove <unistd.h> include from bloatblame, it's no longer needed and the link(2) prototype it drags in was causing warnings whenever I used a local variable named 'link'.
- Use uint32 for all quantities, and double for all differences, so that we can overflow without breaking deltas such as (busy == allocs - frees). This doesn't help sorting, however: if one of the sort keys has overflowed past 0 just a bit, while the other is a very large unsigned number, beware.
- Separate graph link (half an edge, structurally speaking -- no per-edge stats) from graph edge, so that an edge is two links and some stats. This avoids bloat and copying in connect_nodes (which is soon to become generic and move to tmreader.[ch]).
- Factor data structures better: we now have {allocs,frees} x {bytes,calls} x {direct, total}, declaring the second set as struct tmallcounts and the third as tmcounts. So, for example, total number of calls to allocators would be allocs.calls.total; bytes freed directly by a graphnode (library, component, or method) would be frees.bytes.direct.
- Teach tmreader_eventloop about 'F' (TM_EVENT_FREE) events: it now updates the direct free byte and call counts for a method, its component, and its library when it reads the event. Of course, bloatblame ignores this info, because it is concerned only with bloat (total memory allocated).
- Right-align numbers in the first (trace-malloc stats) table.
2000-07-26 04:24:08 +04:00
|
|
|
/* Indices into tmgraphedge.links -- out must come first. */
|
|
|
|
#define TM_EDGE_OUT_LINK 0
|
|
|
|
#define TM_EDGE_IN_LINK 1
|
|
|
|
|
|
|
|
#define TM_LINK_TO_EDGE(link,which) ((tmgraphedge*) &(link)[-(which)])
|
|
|
|
|
2000-07-09 12:53:46 +04:00
|
|
|
struct tmcallsite {
|
- Remove <unistd.h> include from bloatblame, it's no longer needed and the link(2) prototype it drags in was causing warnings whenever I used a local variable named 'link'.
- Use uint32 for all quantities, and double for all differences, so that we can overflow without breaking deltas such as (busy == allocs - frees). This doesn't help sorting, however: if one of the sort keys has overflowed past 0 just a bit, while the other is a very large unsigned number, beware.
- Separate graph link (half an edge, structurally speaking -- no per-edge stats) from graph edge, so that an edge is two links and some stats. This avoids bloat and copying in connect_nodes (which is soon to become generic and move to tmreader.[ch]).
- Factor data structures better: we now have {allocs,frees} x {bytes,calls} x {direct, total}, declaring the second set as struct tmallcounts and the third as tmcounts. So, for example, total number of calls to allocators would be allocs.calls.total; bytes freed directly by a graphnode (library, component, or method) would be frees.bytes.direct.
- Teach tmreader_eventloop about 'F' (TM_EVENT_FREE) events: it now updates the direct free byte and call counts for a method, its component, and its library when it reads the event. Of course, bloatblame ignores this info, because it is concerned only with bloat (total memory allocated).
- Right-align numbers in the first (trace-malloc stats) table.
2000-07-26 04:24:08 +04:00
|
|
|
PLHashEntry entry; /* key is site serial number */
|
|
|
|
tmcallsite *parent; /* calling site */
|
|
|
|
tmcallsite *siblings; /* other sites reached from parent */
|
|
|
|
tmcallsite *kids; /* sites reached from here */
|
|
|
|
tmgraphnode *method; /* method node in tmr->methods graph */
|
|
|
|
uint32 offset; /* pc offset from start of method */
|
|
|
|
tmallcounts allocs;
|
|
|
|
tmallcounts frees;
|
2000-07-09 12:53:46 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
struct tmreader {
|
|
|
|
const char *program;
|
|
|
|
void *data;
|
|
|
|
PLHashTable *libraries;
|
|
|
|
PLHashTable *components;
|
|
|
|
PLHashTable *methods;
|
|
|
|
PLHashTable *callsites;
|
|
|
|
tmcallsite calltree_root;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef void (*tmeventhandler)(tmreader *tmr, tmevent *event);
|
|
|
|
|
2000-07-22 00:42:15 +04:00
|
|
|
/* The tmreader constructor and destructor. */
|
2000-07-09 12:53:46 +04:00
|
|
|
extern tmreader *tmreader_new(const char *program, void *data);
|
|
|
|
extern void tmreader_destroy(tmreader *tmr);
|
2000-07-22 00:42:15 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Return -1 on permanent fatal error, 0 if filename can't be opened or is not
|
|
|
|
* a trace-malloc logfile, and 1 on success.
|
|
|
|
*/
|
|
|
|
extern int tmreader_eventloop(tmreader *tmr, const char *filename,
|
|
|
|
tmeventhandler eventhandler);
|
|
|
|
|
|
|
|
/* Map serial number or name to graphnode or callsite. */
|
|
|
|
extern tmgraphnode *tmreader_library(tmreader *tmr, uint32 serial);
|
|
|
|
extern tmgraphnode *tmreader_component(tmreader *tmr, const char *name);
|
|
|
|
extern tmgraphnode *tmreader_method(tmreader *tmr, uint32 serial);
|
|
|
|
extern tmcallsite *tmreader_callsite(tmreader *tmr, uint32 serial);
|
2000-07-09 12:53:46 +04:00
|
|
|
|
2000-07-26 06:19:27 +04:00
|
|
|
/*
|
|
|
|
* Connect node 'from' to node 'to' with an edge, if there isn't one already
|
|
|
|
* connecting the nodes. Add site's allocation stats to the edge only if we
|
|
|
|
* create the edge, or if we find that it exists, but that to->low is zero or
|
|
|
|
* less than from->low.
|
|
|
|
*
|
|
|
|
* If the callsite tree already totals allocation costs (tmcounts.total for
|
|
|
|
* each site includes tmcounts.direct for that site, plus tmcounts.total for
|
|
|
|
* all kid sites), then the node->low watermarks should be set from the tree
|
|
|
|
* level when walking the callsite tree, and should be set to non-zero values
|
|
|
|
* only if zero (the root is at level 0). A low watermark should be cleared
|
|
|
|
* when the tree walk unwinds past the level at which it was set non-zero.
|
|
|
|
*
|
|
|
|
* Return 0 on error (malloc failure) and 1 on success.
|
|
|
|
*/
|
|
|
|
extern int tmgraphnode_connect(tmgraphnode *from, tmgraphnode *to,
|
|
|
|
tmcallsite *site);
|
|
|
|
|
2000-07-09 12:53:46 +04:00
|
|
|
PR_END_EXTERN_C
|
|
|
|
|
|
|
|
#endif /* tmreader_h___ */
|