[svn:parrot] r40855 - in branches/pluggable_runcore: include/parrot src/runcore

cotto at svn.parrot.org cotto at svn.parrot.org
Sat Aug 29 18:09:31 UTC 2009


Author: cotto
Date: Sat Aug 29 18:09:30 2009
New Revision: 40855
URL: https://trac.parrot.org/parrot/changeset/40855

Log:
[profiling] catch the edge case where the file changes on an inner runloop
also, use more STRINGs internally, try (and fail) to abuse ->strstart less and print output filename on interp exit

Modified:
   branches/pluggable_runcore/include/parrot/runcore_api.h
   branches/pluggable_runcore/src/runcore/cores.c

Modified: branches/pluggable_runcore/include/parrot/runcore_api.h
==============================================================================
--- branches/pluggable_runcore/include/parrot/runcore_api.h	Sat Aug 29 17:27:12 2009	(r40854)
+++ branches/pluggable_runcore/include/parrot/runcore_api.h	Sat Aug 29 18:09:30 2009	(r40855)
@@ -40,7 +40,8 @@
 
 typedef enum Parrot_profiling_flags {
     PROFILING_EXIT_CHECK_FLAG = 1 << 0,
-    PROFILING_FIRST_OP_FLAG   = 1 << 1
+    PROFILING_FIRST_OP_FLAG   = 1 << 1,
+    PROFILING_NEW_FILE_FLAG   = 1 << 2
 } Parrot_profiling_flags;
 
 struct profiling_runcore_t {
@@ -52,15 +53,17 @@
     INTVAL                       flags;
 
     /* end of common members */
-    Parrot_profiling_flags   profiling_flags;
-    FILE                    *prof_fd;
-    UINTVAL                  level;      /* how many nested runloops */
-    UINTVAL                  time_size;  /* how big is the following array */
-    UHUGEINTVAL             *time;       /* time spent between DO_OP and start/end of a runcore */
     UHUGEINTVAL              runcore_start;
     UHUGEINTVAL              op_start;
     UHUGEINTVAL              op_finish;
     UHUGEINTVAL              runcore_finish;
+    Parrot_profiling_flags   profiling_flags;
+    FILE                    *profile_fd;
+    STRING                  *profile_filename;
+    STRING                  *prev_runloop_filename;
+    UINTVAL                  level;      /* how many nested runloops */
+    UINTVAL                  time_size;  /* how big is the following array */
+    UHUGEINTVAL             *time;       /* time spent between DO_OP and start/end of a runcore */
 };
 
 
@@ -89,6 +92,10 @@
 #define Profiling_first_op_SET(o)   Profiling_flag_SET(FIRST_OP, o)
 #define Profiling_first_op_CLEAR(o) Profiling_flag_CLEAR(FIRST_OP, o)
 
+#define Profiling_new_file_TEST(o)  Profiling_flag_TEST(NEW_FILE, o)
+#define Profiling_new_file_SET(o)   Profiling_flag_SET(NEW_FILE, o)
+#define Profiling_new_file_CLEAR(o) Profiling_flag_CLEAR(NEW_FILE, o)
+
 
 #define Runcore_flag_SET(runcore, flag) \
     ((runcore)->flags |= flag)

Modified: branches/pluggable_runcore/src/runcore/cores.c
==============================================================================
--- branches/pluggable_runcore/src/runcore/cores.c	Sat Aug 29 17:27:12 2009	(r40854)
+++ branches/pluggable_runcore/src/runcore/cores.c	Sat Aug 29 18:09:30 2009	(r40855)
@@ -1041,17 +1041,20 @@
 {
     ASSERT_ARGS(init_profiling_core)
 
+    runcore->profile_filename = Parrot_sprintf_c(interp, "parrot.%d.pprof", getpid());
+
     runcore->runops  = (Parrot_runcore_runops_fn_t)  runops_profiling_core;
     runcore->destroy = (Parrot_runcore_destroy_fn_t) destroy_profiling_core;
 
-    runcore->profiling_flags = 0;
-    runcore->level           = 0;
-    runcore->time_size       = 32;
-    runcore->time            = mem_allocate_n_typed(runcore->time_size, UHUGEINTVAL);
-    runcore->prof_fd         = fopen("parrot.pprof", "w");
+    runcore->prev_runloop_filename = NULL;
+    runcore->profiling_flags       = 0;
+    runcore->level                 = 0;
+    runcore->time_size             = 32;
+    runcore->time                  = mem_allocate_n_typed(runcore->time_size, UHUGEINTVAL);
+    runcore->profile_fd            = fopen(runcore->profile_filename->strstart, "w");
 
-    if (!runcore->prof_fd) {
-        fprintf(stderr, "unable to open parrot_prof.out for writing");
+    if (!runcore->profile_fd) {
+        fprintf(stderr, "unable to open %s for writing", runcore->profile_filename->strstart);
         exit(1);
     }
 
@@ -1084,9 +1087,13 @@
     PMC                *preop_sub;
     opcode_t           *preop_pc;
     UHUGEINTVAL         op_time;
-    char                unknown_file[] = "<unknown file>";
+    STRING             *unknown_file = CONST_STRING(interp, "<unknown file>");
 
     runcore->runcore_start = Parrot_hires_get_time();
+    /* profile_filename appears to get prematurely recycled if it's not marked.
+     * Manually marking it or adding an unused STRING variable that points at
+     * it keeps it from an untimely demise. */
+    Parrot_gc_mark_PObj_alive(interp, (PObj*)runcore->profile_filename);
 
     /* if we're in a nested runloop, */
     if (runcore->level != 0) {
@@ -1104,19 +1111,32 @@
 
     Parrot_Context_get_info(interp, CONTEXT(interp), &postop_info);
 
+    /* detect if the current file has changed while entering an inner runloop */
+    if (Parrot_str_compare(interp, runcore->prev_runloop_filename, postop_info.file))
+        Profiling_new_file_SET(runcore);
+    runcore->prev_runloop_filename = postop_info.file;
+
     if (Profiling_first_op_TEST(runcore)) {
-        Profiling_first_op_CLEAR(runcore);
-        fprintf(runcore->prof_fd, "F:%s\n", postop_info.file->strstart);
-        fprintf(runcore->prof_fd, "CS:%s;%s at 0x%X,0x%X\n",
+        
+        PMC    *argv         = VTABLE_get_pmc_keyed_int(interp, interp->iglobals, IGLOBALS_ARGV_LIST);
+        STRING *command_line = Parrot_str_join(interp, CONST_STRING(interp, " "), argv);
+        PMC    *executable   = VTABLE_get_pmc_keyed_int(interp, interp->iglobals, IGLOBALS_EXECUTABLE);
+
+        /* The CLI line won't reflect any options passed to the parrot binary. */
+        fprintf(runcore->profile_fd, "CLI:%s %s\n", VTABLE_get_string(interp, executable)->strstart, command_line->strstart);
+        fprintf(runcore->profile_fd, "F:%s\n", postop_info.file->strstart);
+        fprintf(runcore->profile_fd, "CS:%s;%s at 0x%X,0x%X\n",
                 VTABLE_get_string(interp, CONTEXT(interp)->current_namespace)->strstart,
                 VTABLE_get_string(interp, CONTEXT(interp)->current_sub)->strstart,
                 (unsigned int) CONTEXT(interp)->current_sub,
                 (unsigned int) CONTEXT(interp));
+
+        Profiling_first_op_CLEAR(runcore);
     }
 
     while (pc) {
 
-        char *preop_file_name, *postop_file_name;
+        STRING *preop_file_name, *postop_file_name;
 
         if (pc < code_start || pc >= code_end) {
             Parrot_ex_throw_from_c_args(interp, NULL, 1,
@@ -1127,7 +1147,7 @@
         mem_sys_memcopy(&preop_info, &postop_info, sizeof (Parrot_Context_info));
 
         Parrot_Context_get_info(interp, CONTEXT(interp), &postop_info);
-        preop_file_name = preop_info.file->strstart;
+        preop_file_name = preop_info.file;
 
         CONTEXT(interp)->current_pc = pc;
         preop_sub = CONTEXT(interp)->current_sub;
@@ -1149,15 +1169,17 @@
         }
 
         runcore->level--;
-        postop_file_name = postop_info.file->strstart;
+        postop_file_name = postop_info.file;
 
         if (!preop_file_name)  preop_file_name  = unknown_file;
         if (!postop_file_name) postop_file_name = unknown_file;
 
-        if (strcmp(preop_file_name, postop_file_name))
-            fprintf(runcore->prof_fd, "F:%s\n", postop_file_name);
+        if (Profiling_new_file_TEST(runcore) || Parrot_str_compare(interp, preop_file_name, postop_file_name)) {
+            Profiling_new_file_CLEAR(runcore);
+            fprintf(runcore->profile_fd, "F:%s\n", postop_file_name->strstart);
+        }
 
-        fprintf(runcore->prof_fd, "%d:%lli:%s\n",
+        fprintf(runcore->profile_fd, "%d:%lli:%s\n",
                 postop_info.line, op_time,
                 (interp->op_info_table)[*preop_pc].name);
 
@@ -1168,7 +1190,7 @@
             if (CONTEXT(interp)->current_sub) {
                 STRING *sub_name;
                 GETATTR_Sub_name(interp, CONTEXT(interp)->current_sub, sub_name);
-                fprintf(runcore->prof_fd, "CS:%s;%s at 0x%X,0x%X\n",
+                fprintf(runcore->profile_fd, "CS:%s;%s at 0x%X,0x%X\n",
                         VTABLE_get_string(interp, CONTEXT(interp)->current_namespace)->strstart,
                         sub_name->strstart,
                         (unsigned int) CONTEXT(interp)->current_sub,
@@ -1177,10 +1199,12 @@
         }
     } /* while (pc) */
 
+    if (runcore->level == 0) {
+        fprintf(stderr, "\nPROFILING RUNCORE: Wrote profile to %s .\n", runcore->profile_filename->strstart);
+    }
     Profiling_exit_check_SET(runcore);
     runcore->runcore_finish = Parrot_hires_get_time();;
     return pc;
-
 }
 
 
@@ -1201,7 +1225,7 @@
 {
     ASSERT_ARGS(destroy_profiling_core)
 
-    fclose(runcore->prof_fd);
+    fclose(runcore->profile_fd);
     mem_sys_free(runcore->time);
 
     return NULL;


More information about the parrot-commits mailing list