--- 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 #include #include +#include +#include + +#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 +#include +#include +#include +#include +#include #ifdef DEBUG #include "Trace.h" @@ -50,8 +55,8 @@ static char *prof_filename; /* prof report file name = .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 .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 #include +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.