--- ghc-6.10.2.orig/rts/ProfHeap.c	2009-03-31 06:13:15.000000000 +1300
+++ ghc-6.10.2-profiling/rts/ProfHeap.c	2009-07-13 18:02:02.000000000 +1200
@@ -22,6 +22,57 @@
 #include <string.h>
 #include <stdlib.h>
 #include <math.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#if defined(THREADED_RTS)
+static Mutex hpMutex;
+#endif
+
+#define HPBUF_SIZE 0x80000
+
+static char* hpBuf;
+static int hpBufIdx = 0;
+
+void hpInit(void);
+void hpInit()
+{
+#if defined(THREADED_RTS)
+    initMutex(&hpMutex);
+#endif
+    hpBuf = (char*)malloc(HPBUF_SIZE);
+    hpBufIdx = 0;
+}
+
+void hpprintf(const char* fmt, ...);
+void hpprintf(const char* fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    ACQUIRE_LOCK(&hpMutex);
+    if (hpBufIdx < HPBUF_SIZE - 4096)
+        hpBufIdx += vsprintf(hpBuf+hpBufIdx, fmt, ap);
+    RELEASE_LOCK(&hpMutex);
+}
+
+char* hpPull(int* len);
+char* hpPull(int* len)
+{
+    char* b;
+    ACQUIRE_LOCK(&hpMutex);
+    b = (char*)malloc(hpBufIdx == 0 ? 1 : hpBufIdx);
+    memcpy(b, hpBuf, hpBufIdx);
+    *len = hpBufIdx;
+    hpBufIdx = 0;
+    RELEASE_LOCK(&hpMutex);
+    return b;
+}
+
+void hpFree(char* buf);
+void hpFree(char* buf)
+{
+    free(buf);
+}
 
 /* -----------------------------------------------------------------------------
  * era stores the current time period.  It is the same as the
@@ -384,8 +435,6 @@
  * ------------------------------------------------------------------------- */
 
 #if !defined(PROFILING)
-FILE *hp_file;
-static char *hp_filename;
 
 void initProfiling1 (void)
 {
@@ -413,17 +462,7 @@
 #endif
 
   if (RtsFlags.ProfFlags.doHeapProfile) {
-    /* Initialise the log file name */
-    hp_filename = stgMallocBytes(strlen(prog) + 6, "hpFileName");
-    sprintf(hp_filename, "%s.hp", prog);
-    
-    /* open the log file */
-    if ((hp_file = fopen(hp_filename, "w")) == NULL) {
-      debugBelch("Can't open profiling report file %s\n", 
-	      hp_filename);
-      RtsFlags.ProfFlags.doHeapProfile = 0;
-      return;
-    }
+      hpInit();
   }
   
   stgFree(prog);
@@ -442,7 +481,7 @@
 {
     StgDouble fractionalPart, integralPart;
     fractionalPart = modf(sampleValue, &integralPart);
-    fprintf(hp_file, "%s %" FMT_Word64 ".%02" FMT_Word64 "\n",
+    hpprintf("%s %" FMT_Word64 ".%02" FMT_Word64 "\n",
             (beginSample ? "BEGIN_SAMPLE" : "END_SAMPLE"),
             (StgWord64)integralPart, (StgWord64)(fractionalPart * 100));
 }
@@ -484,25 +523,25 @@
     initEra( &censuses[era] );
 
     /* initProfilingLogFile(); */
-    fprintf(hp_file, "JOB \"%s", prog_name);
+    hpprintf("JOB \"%s", prog_name);
 
 #ifdef PROFILING
     {
 	int count;
 	for(count = 1; count < prog_argc; count++)
-	    fprintf(hp_file, " %s", prog_argv[count]);
-	fprintf(hp_file, " +RTS");
+	    hpprintf(" %s", prog_argv[count]);
+	hpprintf(" +RTS");
 	for(count = 0; count < rts_argc; count++)
-	    fprintf(hp_file, " %s", rts_argv[count]);
+	    hpprintf(" %s", rts_argv[count]);
     }
 #endif /* PROFILING */
 
-    fprintf(hp_file, "\"\n" );
+    hpprintf("\"\n" );
 
-    fprintf(hp_file, "DATE \"%s\"\n", time_str());
+    hpprintf("DATE \"%s\"\n", time_str());
 
-    fprintf(hp_file, "SAMPLE_UNIT \"seconds\"\n");
-    fprintf(hp_file, "VALUE_UNIT \"bytes\"\n");
+    hpprintf("SAMPLE_UNIT \"seconds\"\n");
+    hpprintf("VALUE_UNIT \"bytes\"\n");
 
     printSample(rtsTrue, 0);
     printSample(rtsFalse, 0);
@@ -560,7 +599,7 @@
     seconds = mut_user_time();
     printSample(rtsTrue, seconds);
     printSample(rtsFalse, seconds);
-    fclose(hp_file);
+    /*fclose(hp_file);*/
 }
 
 
@@ -579,17 +618,17 @@
 }
 
 static void
-fprint_ccs(FILE *fp, CostCentreStack *ccs, nat max_length)
+hpprint_ccs(CostCentreStack *ccs, nat max_length)
 {
     char buf[max_length+1], *p, *buf_end;
 
     // MAIN on its own gets printed as "MAIN", otherwise we ignore MAIN.
     if (ccs == CCS_MAIN) {
-	fprintf(fp, "MAIN");
+	hpprintf("MAIN");
 	return;
     }
 
-    fprintf(fp, "(%ld)", ccs->ccsID);
+    hpprintf("(%ld)", ccs->ccsID);
 
     p = buf;
     buf_end = buf + max_length + 1;
@@ -615,7 +654,7 @@
 	    break;
 	}
     }
-    fprintf(fp, "%s", buf);
+    hpprintf("%s", buf);
 }
 #endif /* PROFILING */
 
@@ -818,14 +857,14 @@
 
 #ifdef PROFILING
     if (RtsFlags.ProfFlags.doHeapProfile == HEAP_BY_LDV) {
-      fprintf(hp_file, "VOID\t%lu\n", (unsigned long)(census->void_total) * sizeof(W_));
-	fprintf(hp_file, "LAG\t%lu\n", 
+      hpprintf("VOID\t%lu\n", (unsigned long)(census->void_total) * sizeof(W_));
+	hpprintf("LAG\t%lu\n", 
 		(unsigned long)(census->not_used - census->void_total) * sizeof(W_));
-	fprintf(hp_file, "USE\t%lu\n", 
+	hpprintf("USE\t%lu\n", 
 		(unsigned long)(census->used - census->drag_total) * sizeof(W_));
-	fprintf(hp_file, "INHERENT_USE\t%lu\n", 
+	hpprintf("INHERENT_USE\t%lu\n", 
 		(unsigned long)(census->prim) * sizeof(W_));
-	fprintf(hp_file, "DRAG\t%lu\n",
+	hpprintf("DRAG\t%lu\n",
 		(unsigned long)(census->drag_total) * sizeof(W_));
 	printSample(rtsFalse, census->time);
 	return;
@@ -858,7 +897,7 @@
 #if !defined(PROFILING)
 	switch (RtsFlags.ProfFlags.doHeapProfile) {
 	case HEAP_BY_CLOSURE_TYPE:
-	    fprintf(hp_file, "%s", (char *)ctr->identity);
+	    hpprintf("%s", (char *)ctr->identity);
 	    break;
 	}
 #endif
@@ -866,12 +905,12 @@
 #ifdef PROFILING
 	switch (RtsFlags.ProfFlags.doHeapProfile) {
 	case HEAP_BY_CCS:
-	    fprint_ccs(hp_file, (CostCentreStack *)ctr->identity, RtsFlags.ProfFlags.ccsLength);
+	    hpprint_ccs((CostCentreStack *)ctr->identity, RtsFlags.ProfFlags.ccsLength);
 	    break;
 	case HEAP_BY_MOD:
 	case HEAP_BY_DESCR:
 	case HEAP_BY_TYPE:
-	    fprintf(hp_file, "%s", (char *)ctr->identity);
+	    hpprintf("%s", (char *)ctr->identity);
 	    break;
 	case HEAP_BY_RETAINER:
 	{
@@ -879,7 +918,7 @@
 
 	    // it might be the distinguished retainer set rs_MANY:
 	    if (rs == &rs_MANY) {
-		fprintf(hp_file, "MANY");
+		hpprintf("MANY");
 		break;
 	    }
 
@@ -893,7 +932,7 @@
 		rs->id = -(rs->id);
 
 	    // report in the unit of bytes: * sizeof(StgWord)
-	    printRetainerSetShort(hp_file, rs);
+	    printRetainerSetShort(rs);
 	    break;
 	}
 	default:
@@ -901,7 +940,7 @@
 	}
 #endif
 
-	fprintf(hp_file, "\t%lu\n", (unsigned long)count * sizeof(W_));
+	hpprintf("\t%lu\n", (unsigned long)count * sizeof(W_));
     }
 
     printSample(rtsFalse, census->time);
--- ghc-6.10.2.orig/rts/Profiling.c	2009-03-31 06:13:15.000000000 +1300
+++ ghc-6.10.2-profiling/rts/Profiling.c	2009-08-20 09:38:57.000000000 +1200
@@ -21,6 +21,11 @@
 #include "LdvProfile.h"
 
 #include <string.h>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netdb.h>
 
 #ifdef DEBUG
 #include "Trace.h"
@@ -50,8 +55,8 @@
 static char *prof_filename; /* prof report file name = <program>.prof */
 FILE *prof_file;
 
-static char *hp_filename;	/* heap profile (hp2ps style) log file */
-FILE *hp_file;
+void hpInit(void);
+void hpprintf(const char* fmt, ...);
 
 /* The Current Cost Centre Stack (for attributing costs)
  */
@@ -136,7 +141,8 @@
 static  void              ccsSetSelected  ( CostCentreStack *ccs );
 
 static  void              initTimeProfiling   ( void );
-static  void              initProfilingLogFile( void );
+static  void              initProfilingLogFile1( void );
+static  void              initProfilingLogFile2( void );
 
 static  void              reportCCS_XML       ( CostCentreStack *ccs );
 
@@ -200,7 +206,7 @@
 
   /* Set up the log file, and dump the header and cost centre
    * information into it.  */
-  initProfilingLogFile();
+  initProfilingLogFile1();
 
   /* find all the "special" cost centre stacks, and make them children
    * of CCS_MAIN.
@@ -264,9 +270,25 @@
     return;
 }
 
+static char consoleHost[129];
+static int  consolePort = 0;
+
+void configureRemoteConsole(const char* host, int port);
+void configureRemoteConsole(const char* host, int port)
+{
+    strcpy(consoleHost, host);
+    consolePort = port;
+}
 
 static void
-initProfilingLogFile(void)
+initProfilingLogFile1(void)  /* Called at the start of the program */
+{
+    if (RtsFlags.ProfFlags.doHeapProfile)
+        hpInit();
+}
+
+static void
+initProfilingLogFile2(void)  /* Called on exit */
 {
     char *prog;
 
@@ -283,8 +305,9 @@
     }
 #endif
 
-    if (RtsFlags.CcFlags.doCostCentres == 0 && 
-        RtsFlags.ProfFlags.doHeapProfile != HEAP_BY_RETAINER)
+    fprintf(stderr, "initProfilingLogFile2() host=%s port=%d\n", consoleHost, consolePort);  // ###
+    if ((RtsFlags.CcFlags.doCostCentres == 0 && 
+        RtsFlags.ProfFlags.doHeapProfile != HEAP_BY_RETAINER) || consolePort == 0)
     {
         /* No need for the <prog>.prof file */
         prof_filename = NULL;
@@ -295,7 +318,9 @@
         /* Initialise the log file name */
         prof_filename = arenaAlloc(prof_arena, strlen(prog) + 6);
         sprintf(prof_filename, "%s.prof", prog);
+        prof_file = NULL;
 
+#if 0
         /* open the log file */
         if ((prof_file = fopen(prof_filename, "w")) == NULL) {
             debugBelch("Can't open profiling report file %s\n", prof_filename);
@@ -306,6 +331,43 @@
                 RtsFlags.ProfFlags.doHeapProfile = 0;
             return;
         }
+#endif
+        struct sockaddr_in addr;
+        int fd = socket(AF_INET, SOCK_STREAM, 0);
+        int ret;
+        if (fd < 0) {
+            fprintf(stderr, "Can't create socket: %s\n", strerror(errno));
+            return;
+        }
+            // On Linux, gethostbyname will happily accept a numeric IP address, but
+            // on Solaris we need to call 'inet_addr'.
+        {
+            addr.sin_family = AF_INET;
+            addr.sin_port = htons(consolePort);
+            addr.sin_addr.s_addr = inet_addr(consoleHost);
+            if (addr.sin_addr.s_addr == (in_addr_t)-1) {
+                struct hostent* ent = gethostbyname(consoleHost);
+                if (ent == NULL || ent->h_addr_list[0] == NULL) {
+                    fprintf(stderr, "Couldn't resolve host name: %s\n", consoleHost);
+                    return;
+                }
+                addr.sin_addr = *(struct in_addr*)ent->h_addr_list[0];
+            }
+        }
+        
+        ret = connect(fd, &addr, sizeof(addr));
+        if (ret < 0) {
+            fprintf(stderr, "Can't connect to %s%d: %s\n", consoleHost, consolePort, strerror(errno));
+            return;
+        }
+
+        prof_file = fdopen(fd, "w");
+        if (prof_file == NULL) {
+            fprintf(stderr, "fdopen failed: %s\n", strerror(errno));
+        }
+        // Tell the console what file to write to.
+        fputc(strlen(prof_filename), prof_file);
+        fputs(prof_filename, prof_file);
 
         if (RtsFlags.CcFlags.doCostCentres == COST_CENTRES_XML) {
             /* dump the time, and the profiling interval */
@@ -322,20 +384,6 @@
             }
         }
     }
-    
-    if (RtsFlags.ProfFlags.doHeapProfile) {
-	/* Initialise the log file name */
-	hp_filename = arenaAlloc(prof_arena, strlen(prog) + 6);
-	sprintf(hp_filename, "%s.hp", prog);
-
-	/* open the log file */
-	if ((hp_file = fopen(hp_filename, "w")) == NULL) {
-	    debugBelch("Can't open profiling report file %s\n", 
-		    hp_filename);
-	    RtsFlags.ProfFlags.doHeapProfile = 0;
-	    return;
-	}
-    }
 }
 
 void
@@ -679,8 +727,8 @@
     }
   }
   
-  fprintf(prof_file, "%-30s %-20s", "COST CENTRE", "MODULE");  
-  fprintf(prof_file, "%6s %6s", "%time", "%alloc");
+  fprintf(prof_file, "%-64s %-20s", "COST CENTRE", "MODULE");  
+  fprintf(prof_file, "%7s %7s", "%time", "%alloc");
   if (RtsFlags.CcFlags.doCostCentres >= COST_CENTRES_VERBOSE) {
     fprintf(prof_file, "  %5s %9s", "ticks", "bytes");
   }
@@ -690,8 +738,8 @@
       if (cc_to_ignore(cc)) {
 	  continue;
       }
-      fprintf(prof_file, "%-30s %-20s", cc->label, cc->module);
-      fprintf(prof_file, "%6.1f %6.1f",
+      fprintf(prof_file, "%-64s %-20s", cc->label, cc->module);
+      fprintf(prof_file, "%7.2f %7.2f",
 	      total_prof_ticks == 0 ? 0.0 : (cc->time_ticks / (StgFloat) total_prof_ticks * 100),
 	      total_alloc == 0 ? 0.0 : (cc->mem_alloc / (StgFloat)
 					total_alloc * 100)
@@ -714,10 +762,10 @@
 static void 
 fprint_header( void )
 {
-  fprintf(prof_file, "%-24s %-10s                                                            individual    inherited\n", "", "");
+  fprintf(prof_file, "%-64s %-10s                                                            individual    inherited\n", "", "");
 
-  fprintf(prof_file, "%-24s %-50s", "COST CENTRE", "MODULE");  
-  fprintf(prof_file, "%6s %10s  %5s %5s   %5s %5s", "no.", "entries", "%time", "%alloc", "%time", "%alloc");
+  fprintf(prof_file, "%-64s %-50s", "COST CENTRE", "MODULE");  
+  fprintf(prof_file, "%6s %10s  %6s %6s   %6s %6s", "no.", "entries", "%time", "%alloc", "%time", "%alloc");
 
   if (RtsFlags.CcFlags.doCostCentres >= COST_CENTRES_VERBOSE) {
     fprintf(prof_file, "  %5s %9s", "ticks", "bytes");
@@ -737,6 +785,7 @@
     char temp[128]; /* sigh: magic constant */
 
     stopProfTimer();
+    initProfilingLogFile2();
 
     total_prof_ticks = 0;
     total_alloc = 0;
@@ -804,9 +853,9 @@
     {
 
     fprintf(prof_file, "%-*s%-*s %-50s", 
-	    indent, "", 24-indent, cc->label, cc->module);
+	    indent, "", 64-indent, cc->label, cc->module);
 
-    fprintf(prof_file, "%6ld %11.0f %5.1f  %5.1f   %5.1f  %5.1f",
+    fprintf(prof_file, "%6ld %11.0f %6.2f  %6.2f   %6.2f  %6.2f",
 	    ccs->ccsID, (double) ccs->scc_count, 
 	    total_prof_ticks == 0 ? 0.0 : ((double)ccs->time_ticks / (double)total_prof_ticks * 100.0),
 	    total_alloc == 0 ? 0.0 : ((double)ccs->mem_alloc / (double)total_alloc * 100.0),
--- ghc-6.10.2.orig/rts/RetainerSet.c	2009-03-31 06:13:15.000000000 +1300
+++ ghc-6.10.2-profiling/rts/RetainerSet.c	2009-07-13 17:42:40.000000000 +1200
@@ -20,6 +20,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+void hpprintf(const char* fmt, ...);
+
 #define HASH_TABLE_SIZE 255
 #define hash(hk)  (hk % HASH_TABLE_SIZE)
 static RetainerSet *hashTable[HASH_TABLE_SIZE];
@@ -265,7 +267,7 @@
 #if defined(RETAINER_SCHEME_INFO)
 // Retainer scheme 1: retainer = info table
 void
-printRetainerSetShort(FILE *f, RetainerSet *rs)
+printRetainerSetShort(RetainerSet *rs)
 {
 #define MAX_RETAINER_SET_SPACE  24
     char tmp[MAX_RETAINER_SET_SPACE + 1];
@@ -297,12 +299,12 @@
 	    // size = strlen(tmp);
 	}
     }
-    fprintf(f, tmp);
+    hpprintf(tmp);
 }
 #elif defined(RETAINER_SCHEME_CC)
 // Retainer scheme 3: retainer = cost centre
 void
-printRetainerSetShort(FILE *f, RetainerSet *rs)
+printRetainerSetShort(RetainerSet *rs)
 {
 #define MAX_RETAINER_SET_SPACE  24
     char tmp[MAX_RETAINER_SET_SPACE + 1];
@@ -313,7 +315,7 @@
 #elif defined(RETAINER_SCHEME_CCS)
 // Retainer scheme 2: retainer = cost centre stack
 void
-printRetainerSetShort(FILE *f, RetainerSet *rs)
+printRetainerSetShort(RetainerSet *rs)
 {
 #define MAX_RETAINER_SET_SPACE  24
     char tmp[MAX_RETAINER_SET_SPACE + 1];
@@ -345,12 +347,12 @@
 	    // size = strlen(tmp);
 	}
     }
-    fprintf(f, tmp);
+    hpprintf(tmp);
 }
 #elif defined(RETAINER_SCHEME_CC)
 // Retainer scheme 3: retainer = cost centre
 static void
-printRetainerSetShort(FILE *f, retainerSet *rs)
+printRetainerSetShort(retainerSet *rs)
 {
 #define MAX_RETAINER_SET_SPACE  24
     char tmp[MAX_RETAINER_SET_SPACE + 1];
@@ -384,7 +386,7 @@
 	    // size = strlen(tmp);
 	}
     }
-    fprintf(f, tmp);
+    hpprintf(tmp);
 /*
   #define MAX_RETAINER_SET_SPACE  24
   #define DOT_NUMBER              3
--- ghc-6.10.2.orig/rts/RetainerSet.h	2009-03-31 06:13:15.000000000 +1300
+++ ghc-6.10.2-profiling/rts/RetainerSet.h	2009-07-13 17:42:11.000000000 +1200
@@ -163,7 +163,7 @@
 
 #ifdef SECOND_APPROACH
 // Prints a single retainer set.
-void printRetainerSetShort(FILE *, RetainerSet *);
+void printRetainerSetShort(RetainerSet *);
 #endif
 
 // Print the statistics on all the retainer sets.
