rts: Allow profile output path to be specified on RTS command line
authorBen Gamari <bgamari.foss@gmail.com>
Tue, 28 Feb 2017 14:31:06 +0000 (09:31 -0500)
committerBen Gamari <ben@smart-cactus.org>
Tue, 28 Feb 2017 15:56:11 +0000 (10:56 -0500)
This introduces a RTS option, -po, which allows the user to override the stem
used to form the output file names of the heap profile and cost center summary.

It's a bit unclear to me whether this is really the interface we want.
Alternatively we could just allow the user to specify the `.hp` and `.prof` file
names separately. This would arguably be a bit more straightforward and would
allow the user to name JSON output with an appropriate `.json` suffix if they so
desired. However, this would come at the cost of taking more of the option
space, which is a somewhat precious commodity.

Test Plan: Validate, try using `-po` RTS option

Reviewers: simonmar, austin, erikd

Reviewed By: simonmar

Subscribers: thomie

Differential Revision: https://phabricator.haskell.org/D3182

docs/users_guide/profiling.rst
includes/rts/Flags.h
rts/Profiling.c
rts/RtsFlags.c

index 764ee92..832464e 100644 (file)
@@ -402,7 +402,8 @@ enclosed between ``+RTS ... -RTS`` as usual):
        single: time profile
 
     The :rts-flag:`-p` option produces a standard *time profile* report. It is
-    written into the file :file:`program.prof`.
+    written into the file :file:`<stem>.prof`; the stem is taken to be the program
+    name by default, but can be overridden by the :rts-flag:`-po` flag.
 
     The :rts-flag:`-P` option produces a more detailed report containing the
     actual time and allocation data as well. (Not used much.)
@@ -415,6 +416,16 @@ enclosed between ``+RTS ... -RTS`` as usual):
     The :rts-flag:`-pj` option produces a time/allocation profile report in JSON
     format written into the file :file:`<program>.prof`.
 
+.. rts-flag:: -po ⟨stem⟩
+
+    The :rts-flag:`-po` option overrides the stem used to form the output file
+    paths for the cost-center profiler (see :rts-flag:`-p` and :rts-flag:`-pj`
+    flags above) and heap profiler (see :rts-flag:`-h`).
+
+    For instance, running a program with ``+RTS -h -p -pohello-world`` would
+    produce a heap profile named :file:`hello-world.hp` and a cost-center
+    profile named :file:`hello-world.prof`.
+
 .. rts-flag:: -V <secs>
 
     Sets the interval that the RTS clock ticks at, which is also the
index ebcf973..c8f71d1 100644 (file)
@@ -119,6 +119,7 @@ typedef struct _COST_CENTRE_FLAGS {
 
     int            profilerTicks;   /* derived */
     int            msecsPerTick;    /* derived */
+    char const *oututFileNameStem;
 } COST_CENTRE_FLAGS;
 
 /* See Note [Synchronization of flags and base APIs] */
index 0dc1e26..c0d60a5 100644 (file)
@@ -228,32 +228,39 @@ CostCentre *mkCostCentre (char *label, char *module, char *srcloc)
 static void
 initProfilingLogFile(void)
 {
-    char *prog;
+    // Figure out output file name stem.
+    char const *stem;
+    if (RtsFlags.CcFlags.outputFileNameStem) {
+        stem = RtsFlags.CcFlags.outputFileNameStem;
+    } else {
+        char *prog;
 
-    prog = arenaAlloc(prof_arena, strlen(prog_name) + 1);
-    strcpy(prog, prog_name);
+        prog = arenaAlloc(prof_arena, strlen(prog_name) + 1);
+        strcpy(prog, prog_name);
 #ifdef mingw32_HOST_OS
-    // on Windows, drop the .exe suffix if there is one
-    {
-        char *suff;
-        suff = strrchr(prog,'.');
-        if (suff != NULL && !strcmp(suff,".exe")) {
-            *suff = '\0';
+        // on Windows, drop the .exe suffix if there is one
+        {
+            char *suff;
+            suff = strrchr(prog,'.');
+            if (suff != NULL && !strcmp(suff,".exe")) {
+                *suff = '\0';
+            }
         }
-    }
 #endif
+        stem = prog;
+    }
 
     if (RtsFlags.CcFlags.doCostCentres == 0 && !doingRetainerProfiling())
     {
-        /* No need for the <prog>.prof file */
+        /* No need for the <stem>.prof file */
         prof_filename = NULL;
         prof_file = NULL;
     }
     else
     {
         /* Initialise the log file name */
-        prof_filename = arenaAlloc(prof_arena, strlen(prog) + 6);
-        sprintf(prof_filename, "%s.prof", prog);
+        prof_filename = arenaAlloc(prof_arena, strlen(stem) + 6);
+        sprintf(prof_filename, "%s.prof", stem);
 
         /* open the log file */
         if ((prof_file = fopen(prof_filename, "w")) == NULL) {
@@ -269,13 +276,13 @@ initProfilingLogFile(void)
 
     if (RtsFlags.ProfFlags.doHeapProfile) {
         /* Initialise the log file name */
-        hp_filename = arenaAlloc(prof_arena, strlen(prog) + 6);
-        sprintf(hp_filename, "%s.hp", prog);
+        hp_filename = arenaAlloc(prof_arena, strlen(stem) + 6);
+        sprintf(hp_filename, "%s.hp", stem);
 
         /* open the log file */
         if ((hp_file = fopen(hp_filename, "w")) == NULL) {
             debugBelch("Can't open profiling report file %s\n",
-                    hp_filename);
+                       hp_filename);
             RtsFlags.ProfFlags.doHeapProfile = 0;
         }
     }
index 9cff810..8d71354 100644 (file)
@@ -296,14 +296,16 @@ usage_text[] = {
 "  -S[<file>] Detailed GC statistics (if <file> omitted, uses stderr)",
 "",
 "",
-"  -Z       Don't squeeze out update frames on stack overflow",
-"  -B       Sound the bell at the start of each garbage collection",
+"  -Z         Don't squeeze out update frames on stack overflow",
+"  -B         Sound the bell at the start of each garbage collection",
 #if defined(PROFILING)
 "",
-"  -p       Time/allocation profile        (output file <program>.prof)",
-"  -P       More detailed Time/Allocation profile",
-"  -Pa      Give information about *all* cost centres",
-"  -pj      Output cost-center profile in JSON format",
+"  -p         Time/allocation profile in tree format ",
+"             (output file <output prefix>.prof)",
+"  -po<file>  Override profiling output file name prefix (program name by default)",
+"  -P         More detailed Time/Allocation profile in tree format",
+"  -Pa        Give information about *all* cost centres in tree format",
+"  -pj        Output cost-center profile in JSON format",
 "",
 "  -h<break-down> Heap residency profile (hp2ps) (output file <program>.hp)",
 "     break-down: c = cost centre stack (default)",