Improve performance when trace-malloc is built but not used by adding a fast-path around the locking. b=150015 r=brendan a=bzbarsky
authordbaron@dbaron.org
Fri, 10 Aug 2007 14:24:32 -0700
changeset 4483 eae91ec46932cb68df6e7faf1bb49d434d049848
parent 4482 40ff8a30689b8d5a1f5b68ac212e83b7078082f4
child 4484 469e8b19f7066511e65df4eb3d7b460e79794f53
push idunknown
push userunknown
push dateunknown
reviewersbrendan, bzbarsky
bugs150015
milestone1.9a8pre
Improve performance when trace-malloc is built but not used by adding a fast-path around the locking. b=150015 r=brendan a=bzbarsky
tools/trace-malloc/lib/nsTraceMalloc.c
--- a/tools/trace-malloc/lib/nsTraceMalloc.c
+++ b/tools/trace-malloc/lib/nsTraceMalloc.c
@@ -299,16 +299,25 @@ static PRMonitor *tmmon = NULL;
 static char      *sdlogname = NULL; /* filename for shutdown leak log */
 
 /*
  * This counter suppresses tracing, in case any tracing code needs to malloc,
  * and it must be tested and manipulated only within tmmon.
  */
 static uint32 suppress_tracing = 0;
 
+/*
+ * This enables/disables trace-malloc logging.
+ *
+ * It is separate from suppress_tracing so that we do not have to pay
+ * the performance cost of repeated PR_EnterMonitor/PR_ExitMonitor and
+ * PR_IntervalNow calls when trace-malloc is disabled.
+ */
+static int tracing_enabled = 1;
+
 #define TM_ENTER_MONITOR()                                                    \
     PR_BEGIN_MACRO                                                            \
         if (tmmon)                                                            \
             PR_EnterMonitor(tmmon);                                           \
     PR_END_MACRO
 
 #define TM_EXIT_MONITOR()                                                     \
     PR_BEGIN_MACRO                                                            \
@@ -1488,17 +1497,17 @@ NS_EXTERNAL_VIS_(__ptr_t)
 malloc(size_t size)
 {
     PRUint32 start, end;
     __ptr_t ptr;
     callsite *site;
     PLHashEntry *he;
     allocation *alloc;
 
-    if (!PR_Initialized()) {
+    if (!tracing_enabled || !PR_Initialized()) {
         return __libc_malloc(size);
     }
 
     start = PR_IntervalNow();
     ptr = __libc_malloc(size);
     end = PR_IntervalNow();
     TM_ENTER_MONITOR();
     tmstats.malloc_calls++;
@@ -1540,17 +1549,17 @@ calloc(size_t count, size_t size)
      * using calloc (call from _dl_tls_setup).
      *
      * Thus, our calloc replacement is invoked too early, tries to
      * initialize NSPR, which calls dlopen, which calls into the dl
      * -> crash.
      *
      * Delaying NSPR calls until NSPR is initialized helps.
      */
-    if (!PR_Initialized()) {
+    if (!tracing_enabled || !PR_Initialized()) {
         return __libc_calloc(count, size);
     }
 
     start = PR_IntervalNow();
     ptr = __libc_calloc(count, size);
     end = PR_IntervalNow();
     TM_ENTER_MONITOR();
     tmstats.calloc_calls++;
@@ -1586,17 +1595,17 @@ realloc(__ptr_t ptr, size_t size)
     __ptr_t oldptr;
     callsite *oldsite, *site;
     size_t oldsize;
     PLHashNumber hash;
     PLHashEntry **hep, *he;
     allocation *alloc;
     FILE *trackfp = NULL;
 
-    if (!PR_Initialized()) {
+    if (!tracing_enabled || !PR_Initialized()) {
         return __libc_realloc(ptr, size);
     }
 
     TM_ENTER_MONITOR();
     tmstats.realloc_calls++;
     if (suppress_tracing == 0) {
         oldptr = ptr;
         oldsite = NULL;
@@ -1680,17 +1689,17 @@ NS_EXTERNAL_VIS_(void*)
 valloc(size_t size)
 {
     PRUint32 start, end;
     __ptr_t ptr;
     callsite *site;
     PLHashEntry *he;
     allocation *alloc;
 
-    if (!PR_Initialized()) {
+    if (!tracing_enabled || !PR_Initialized()) {
         return __libc_valloc(size);
     }
 
     start = PR_IntervalNow();
     ptr = __libc_valloc(size);
     end = PR_IntervalNow();
     TM_ENTER_MONITOR();
     tmstats.malloc_calls++; /* XXX valloc_calls ? */
@@ -1721,17 +1730,17 @@ NS_EXTERNAL_VIS_(void*)
 memalign(size_t boundary, size_t size)
 {
     PRUint32 start, end;
     __ptr_t ptr;
     callsite *site;
     PLHashEntry *he;
     allocation *alloc;
 
-    if (!PR_Initialized()) {
+    if (!tracing_enabled || !PR_Initialized()) {
         return __libc_memalign(boundary, size);
     }
 
     start = PR_IntervalNow();
     ptr = __libc_memalign(boundary, size);
     end = PR_IntervalNow();
     TM_ENTER_MONITOR();
     tmstats.malloc_calls++; /* XXX memalign_calls ? */
@@ -1773,17 +1782,17 @@ NS_EXTERNAL_VIS_(void)
 free(__ptr_t ptr)
 {
     PLHashEntry **hep, *he;
     callsite *site;
     allocation *alloc;
     uint32 serial = 0, size = 0;
     PRUint32 start, end;
 
-    if (!PR_Initialized()) {
+    if (!tracing_enabled || !PR_Initialized()) {
         __libc_free(ptr);
         return;
     }
 
     TM_ENTER_MONITOR();
     tmstats.free_calls++;
     if (!ptr) {
         tmstats.null_free_calls++;
@@ -1839,36 +1848,37 @@ log_header(int logfd)
     (void) write(logfd, magic, NS_TRACE_MALLOC_MAGIC_SIZE);
     (void) write(logfd, &ticksPerSec, sizeof ticksPerSec);
 }
 
 PR_IMPLEMENT(void) NS_TraceMallocStartup(int logfd)
 {
     /* We must be running on the primordial thread. */
     PR_ASSERT(suppress_tracing == 0);
+    PR_ASSERT(tracing_enabled == 1);
     PR_ASSERT(logfp == &default_logfile);
-    suppress_tracing = (logfd < 0);
+    tracing_enabled = (logfd >= 0);
 
-    if (suppress_tracing == 0) {
+    if (tracing_enabled) {
         PR_ASSERT(logfp->simsize == 0); /* didn't overflow startup buffer */
 
         /* Log everything in logfp (aka default_logfile)'s buffer to logfd. */
         logfp->fd = logfd;
         logfile_list = &default_logfile;
         logfp->prevp = &logfile_list;
         logfile_tail = &logfp->next;
         log_header(logfd);
     }
 
     atexit(NS_TraceMallocShutdown);
     tmmon = PR_NewMonitor();
 
 #ifdef XP_WIN32
     /* Register listeners for win32. */
-    if (suppress_tracing == 0) {
+    if (tracing_enabled) {
         StartupHooker();
     }
 #endif
 }
 
 
 /*
  * Options for log files, with the log file name either as the next option
@@ -2041,37 +2051,37 @@ PR_IMPLEMENT(void) NS_TraceMallocShutdow
         }
     }
     if (tmmon) {
         PRMonitor *mon = tmmon;
         tmmon = NULL;
         PR_DestroyMonitor(mon);
     }
 #ifdef XP_WIN32
-    if (suppress_tracing == 0) {
+    if (tracing_enabled) {
         ShutdownHooker();
     }
 #endif
 }
 
 PR_IMPLEMENT(void) NS_TraceMallocDisable()
 {
     logfile *fp;
 
     TM_ENTER_MONITOR();
     for (fp = logfile_list; fp; fp = fp->next)
         flush_logfile(fp);
-    suppress_tracing++;
+    tracing_enabled = 0;
     TM_EXIT_MONITOR();
 }
 
 PR_IMPLEMENT(void) NS_TraceMallocEnable()
 {
     TM_ENTER_MONITOR();
-    suppress_tracing--;
+    tracing_enabled = 1;
     TM_EXIT_MONITOR();
 }
 
 PR_IMPLEMENT(int) NS_TraceMallocChangeLogFD(int fd)
 {
     logfile *oldfp, *fp;
     struct stat sb;
 
@@ -2282,16 +2292,19 @@ NS_TrackAllocation(void* ptr, FILE *ofp)
 
 PR_IMPLEMENT(void)
 MallocCallback(void *ptr, size_t size, PRUint32 start, PRUint32 end)
 {
     callsite *site;
     PLHashEntry *he;
     allocation *alloc;
 
+    if (!tracing_enabled)
+        return;
+
     TM_ENTER_MONITOR();
     tmstats.malloc_calls++;
     if (!ptr) {
         tmstats.malloc_failures++;
     } else if (suppress_tracing == 0) {
         site = backtrace(4);
         if (site)
             log_event5(logfp, TM_EVENT_MALLOC,
@@ -2312,16 +2325,19 @@ MallocCallback(void *ptr, size_t size, P
 
 PR_IMPLEMENT(void)
 CallocCallback(void *ptr, size_t count, size_t size, PRUint32 start, PRUint32 end)
 {
     callsite *site;
     PLHashEntry *he;
     allocation *alloc;
 
+    if (!tracing_enabled)
+        return;
+
     TM_ENTER_MONITOR();
     tmstats.calloc_calls++;
     if (!ptr) {
         tmstats.calloc_failures++;
     } else if (suppress_tracing == 0) {
         site = backtrace(1);
         size *= count;
         if (site)
@@ -2345,16 +2361,19 @@ PR_IMPLEMENT(void)
 ReallocCallback(void * oldptr, void *ptr, size_t size, PRUint32 start, PRUint32 end)
 {
     callsite *oldsite, *site;
     size_t oldsize;
     PLHashNumber hash;
     PLHashEntry **hep, *he;
     allocation *alloc;
 
+    if (!tracing_enabled)
+        return;
+
     TM_ENTER_MONITOR();
     tmstats.realloc_calls++;
     if (suppress_tracing == 0) {
         oldsite = NULL;
         oldsize = 0;
         he = NULL;
         if (oldptr && get_allocations()) {
             hash = hash_pointer(oldptr);
@@ -2415,16 +2434,19 @@ ReallocCallback(void * oldptr, void *ptr
 
 PR_IMPLEMENT(void)
 FreeCallback(void * ptr, PRUint32 start, PRUint32 end)
 {
     PLHashEntry **hep, *he;
     callsite *site;
     allocation *alloc;
 
+    if (!tracing_enabled)
+        return;
+
     TM_ENTER_MONITOR();
     tmstats.free_calls++;
     if (!ptr) {
         tmstats.null_free_calls++;
     } else if (suppress_tracing == 0) {
         if (get_allocations()) {
             hep = PL_HashTableRawLookup(allocations, hash_pointer(ptr), ptr);
             he = *hep;