[svn:parrot] r42938 - in trunk: include/parrot src/runcore tools/dev
cotto at svn.parrot.org
cotto at svn.parrot.org
Tue Dec 8 08:17:43 UTC 2009
Author: cotto
Date: Tue Dec 8 08:17:41 2009
New Revision: 42938
URL: https://trac.parrot.org/parrot/changeset/42938
Log:
[profiling] various: make output configurable and extensible (and add POC noop output function)
fix a copypasta goof in pprof output code, update pprof2cg.pl to parse the update pprof format
The PARROT_PROFILING_FILENAME env var is now the output filename and
PARROT_PROFILING_OUTPUT is the output type, if defined.
Modified:
trunk/include/parrot/runcore_profiling.h
trunk/src/runcore/profiling.c
trunk/tools/dev/pprof2cg.pl
Modified: trunk/include/parrot/runcore_profiling.h
==============================================================================
--- trunk/include/parrot/runcore_profiling.h Tue Dec 8 05:15:45 2009 (r42937)
+++ trunk/include/parrot/runcore_profiling.h Tue Dec 8 08:17:41 2009 (r42938)
@@ -9,7 +9,7 @@
#ifndef PARROT_RUNCORE_PROFILING_H_GUARD
#define PARROT_RUNCORE_PROFILING_H_GUARD
-struct profiling_runcore_t;
+struct profiling_runcore_t;
typedef struct profiling_runcore_t Parrot_profiling_runcore_t;
#include "parrot/parrot.h"
@@ -37,6 +37,9 @@
PPROF_LINE_END_OF_RUNLOOP
} Parrot_profiling_line;
+typedef void (*profiling_output_fn)(ARGIN(Parrot_profiling_runcore_t*), ARGIN_NULLOK(Parrot_profiling_line));
+typedef profiling_output_fn Parrot_profiling_output_fn;
+
typedef enum Parrot_profiling_datatype {
PPROF_DATA_TIME = 0,
PPROF_DATA_FILENAME,
@@ -59,6 +62,7 @@
INTVAL flags;
/* end of common members */
+ Parrot_profiling_output_fn output_fn;
UHUGEINTVAL runcore_start;
UHUGEINTVAL op_start;
UHUGEINTVAL op_finish;
@@ -76,7 +80,6 @@
PPROF_DATA pprof_data[PPROF_DATA_MAX]; /* array for storage of one line of profiling data */
};
-
#define Profiling_flag_SET(runcore, flag) \
((runcore)->profiling_flags |= flag)
#define Profiling_flag_TEST(runcore, flag) \
Modified: trunk/src/runcore/profiling.c
==============================================================================
--- trunk/src/runcore/profiling.c Tue Dec 8 05:15:45 2009 (r42937)
+++ trunk/src/runcore/profiling.c Tue Dec 8 08:17:41 2009 (r42938)
@@ -57,6 +57,11 @@
ARGIN_NULLOK(Parrot_profiling_line type))
__attribute__nonnull__(1);
+static void record_values_none(
+ ARGIN(Parrot_profiling_runcore_t * runcore),
+ ARGIN_NULLOK(Parrot_profiling_line type))
+ __attribute__nonnull__(1);
+
PARROT_WARN_UNUSED_RESULT
PARROT_CAN_RETURN_NULL
static opcode_t * runops_profiling_core(PARROT_INTERP,
@@ -72,6 +77,8 @@
, PARROT_ASSERT_ARG(pc))
#define ASSERT_ARGS_record_values_ascii_pprof __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(runcore))
+#define ASSERT_ARGS_record_values_none __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+ PARROT_ASSERT_ARG(runcore))
#define ASSERT_ARGS_runops_profiling_core __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(runcore) \
@@ -129,13 +136,14 @@
{
ASSERT_ARGS(init_profiling_core)
- char *profile_filename, *profile_output_var;
+ char *profile_filename, *profile_output_cstr, *profile_filename_cstr;
- profile_output_var = Parrot_getenv(interp, CONST_STRING(interp, "PARROT_PROFILING_OUTPUT"));
+ /* figure out where to write the output */
+ profile_filename_cstr = Parrot_getenv(interp, CONST_STRING(interp, "PARROT_PROFILING_FILENAME"));
- if (profile_output_var) {
+ if (profile_filename_cstr) {
STRING *lc_filename;
- runcore->profile_filename = Parrot_str_new(interp, profile_output_var, 0);
+ runcore->profile_filename = Parrot_str_new(interp, profile_filename_cstr, 0);
profile_filename = Parrot_str_to_cstring(interp, runcore->profile_filename);
lc_filename = Parrot_str_downcase(interp, runcore->profile_filename);
@@ -156,9 +164,39 @@
runcore->profile_fd = fopen(profile_filename, "w");
}
+ if (!runcore->profile_fd) {
+ fprintf(stderr, "unable to open %s for writing", profile_filename);
+ Parrot_str_free_cstring(profile_filename);
+ exit(1);
+ }
+
+ /* figure out what format the output should be in */
+ profile_output_cstr = Parrot_getenv(interp, CONST_STRING(interp, "PARROT_PROFILING_OUTPUT"));
+
+ if (profile_output_cstr) {
+
+ STRING *profile_format_str = Parrot_str_new(interp, profile_output_cstr, 0);
+ if (Parrot_str_equal(interp, profile_format_str, CONST_STRING(interp, "pprof"))) {
+ runcore->output_fn = record_values_ascii_pprof;
+ }
+ else if (Parrot_str_equal(interp, profile_format_str, CONST_STRING(interp, "none"))) {
+ runcore->output_fn = record_values_none;
+ }
+ else {
+ fprintf(stderr, "'%s' is not a valid profiling output format.\n", profile_output_cstr);
+ fprintf(stderr, "Valid values are pprof and none. The default is pprof.\n");
+ exit(1);
+ }
+ }
+ else {
+ runcore->output_fn = record_values_ascii_pprof;
+ }
+
/* profile_filename gets collected if it's not marked or in the root set. */
gc_register_pmc(interp, (PMC *) runcore->profile_filename);
+
+ /* initialize the rest of the runcore struct */
runcore->runops = (Parrot_runcore_runops_fn_t) runops_profiling_core;
runcore->destroy = (Parrot_runcore_destroy_fn_t) destroy_profiling_core;
@@ -172,12 +210,6 @@
UHUGEINTVAL);
Profiling_first_loop_SET(runcore);
- if (!runcore->profile_fd) {
- fprintf(stderr, "unable to open %s for writing", profile_filename);
- Parrot_str_free_cstring(profile_filename);
- exit(1);
- }
-
Parrot_str_free_cstring(profile_filename);
return runops_profiling_core(interp, runcore, pc);
@@ -229,8 +261,9 @@
argv = VTABLE_get_pmc_keyed_int(interp, interp->iglobals, IGLOBALS_ARGV_LIST);
+ /* argv isn't initialized until after :init (etc) subs are executed */
if (argv && !Profiling_have_printed_cli_TEST(runcore)) {
- /* silly way to avoid line length codingstds nit */
+
PMC *iglobals = interp->iglobals;
PMC *executable = VTABLE_get_pmc_keyed_int(interp, iglobals,
IGLOBALS_EXECUTABLE);
@@ -253,49 +286,35 @@
if (Profiling_first_loop_TEST(runcore)) {
- record_values_ascii_pprof(runcore, PPROF_LINE_VERSION);
+ runcore->output_fn(runcore, PPROF_LINE_VERSION);
/* make all separate runloops appear to come from a single source */
runcore->pprof_data[PPROF_DATA_NAMESPACE] = (PPROF_DATA) "main";
runcore->pprof_data[PPROF_DATA_FILENAME] = (PPROF_DATA) "no_file";
runcore->pprof_data[PPROF_DATA_SUB_ADDR] = 1;
runcore->pprof_data[PPROF_DATA_CTX_ADDR] = 1;
- record_values_ascii_pprof(runcore, PPROF_LINE_CONTEXT_SWITCH);
+ runcore->output_fn(runcore, PPROF_LINE_CONTEXT_SWITCH);
runcore->pprof_data[PPROF_DATA_LINE] = runcore->runloop_count;
runcore->pprof_data[PPROF_DATA_TIME] = 0;
runcore->pprof_data[PPROF_DATA_OPNAME] = (PPROF_DATA) "noop";
- record_values_ascii_pprof(runcore, PPROF_LINE_OP);
+ runcore->output_fn(runcore, PPROF_LINE_OP);
runcore->runloop_count++;
Profiling_first_loop_CLEAR(runcore);
}
while (pc) {
- STRING *preop_filename;
Parrot_Context *preop_ctx;
INTVAL preop_line;
+ PMC *preop_ctx_pmc;
if (pc < code_start || pc >= code_end)
Parrot_ex_throw_from_c_args(interp, NULL, 1,
"attempt to access code outside of current code segment");
- preop_ctx = PMC_data_typed(CURRENT_CONTEXT(interp), Parrot_Context*);
- preop_line = hash_value_to_int(interp, runcore->line_cache,
- parrot_hash_get(interp, runcore->line_cache,
- preop_ctx->current_pc));
-
- preop_filename = Parrot_Sub_get_filename_from_pc(interp,
- Parrot_pcc_get_sub(interp, CURRENT_CONTEXT(interp)), pc);
-
- if (preop_line == 0) {
- preop_line = Parrot_Sub_get_line_from_pc(interp,
- Parrot_pcc_get_sub(interp, CURRENT_CONTEXT(interp)),
- preop_ctx->current_pc);
- parrot_hash_put(interp, runcore->line_cache,
- preop_ctx->current_pc, (void *) preop_line);
- }
-
+ preop_ctx_pmc = CURRENT_CONTEXT(interp);
+ preop_ctx = PMC_data_typed(preop_ctx_pmc, Parrot_Context*);
preop_ctx->current_pc = pc;
preop_sub = preop_ctx->current_sub;
preop_pc = pc;
@@ -325,12 +344,15 @@
|| runcore->prev_sub != preop_ctx->current_sub) {
if (preop_ctx->current_sub) {
- STRING *sub_name, *full_ns, *ns_separator;
+ STRING *sub_name, *full_ns, *ns_separator, *preop_filename;
char *full_ns_cstr, *filename_cstr;
STRING *ns_names[MAX_NAMESPACE_DEPTH];
PMC *ns = preop_ctx->current_namespace;
INTVAL i;
+ preop_filename = Parrot_Sub_get_filename_from_pc(interp,
+ Parrot_pcc_get_sub(interp, preop_ctx_pmc), pc);
+
filename_cstr = Parrot_str_to_cstring(interp, preop_filename);
/* build the namespace string */
@@ -362,7 +384,7 @@
runcore->pprof_data[PPROF_DATA_FILENAME] = (PPROF_DATA) filename_cstr;
runcore->pprof_data[PPROF_DATA_SUB_ADDR] = (PPROF_DATA) preop_ctx->current_sub;
runcore->pprof_data[PPROF_DATA_CTX_ADDR] = (PPROF_DATA) preop_ctx;
- record_values_ascii_pprof(runcore, PPROF_LINE_CONTEXT_SWITCH);
+ runcore->output_fn(runcore, PPROF_LINE_CONTEXT_SWITCH);
Parrot_str_free_cstring(full_ns_cstr);
Parrot_str_free_cstring(filename_cstr);
@@ -372,28 +394,40 @@
runcore->prev_sub = preop_ctx->current_sub;
}
+ preop_line = hash_value_to_int(interp, runcore->line_cache,
+ parrot_hash_get(interp, runcore->line_cache,
+ preop_ctx->current_pc));
+
+ if (preop_line == 0) {
+ preop_line = Parrot_Sub_get_line_from_pc(interp,
+ Parrot_pcc_get_sub(interp, preop_ctx_pmc),
+ preop_ctx->current_pc);
+ parrot_hash_put(interp, runcore->line_cache, preop_ctx->current_pc,
+ (void *) preop_line);
+ }
+
runcore->pprof_data[PPROF_DATA_LINE] = preop_line;
runcore->pprof_data[PPROF_DATA_TIME] = op_time;
runcore->pprof_data[PPROF_DATA_OPNAME] =
(PPROF_DATA)(interp->op_info_table)[*preop_pc].name;
- record_values_ascii_pprof(runcore, PPROF_LINE_OP);
+ runcore->output_fn(runcore, PPROF_LINE_OP);
}
/* make it easy to tell separate runloops apart */
if (runcore->level == 0) {
- record_values_ascii_pprof(runcore, PPROF_LINE_END_OF_RUNLOOP);
+ runcore->output_fn(runcore, PPROF_LINE_END_OF_RUNLOOP);
/* make all separate runloops appear to come from a single source */
runcore->pprof_data[PPROF_DATA_NAMESPACE] = (PPROF_DATA) "main";
runcore->pprof_data[PPROF_DATA_FILENAME] = (PPROF_DATA) "no_file";
runcore->pprof_data[PPROF_DATA_SUB_ADDR] = 1;
runcore->pprof_data[PPROF_DATA_CTX_ADDR] = 1;
- record_values_ascii_pprof(runcore, PPROF_LINE_CONTEXT_SWITCH);
+ runcore->output_fn(runcore, PPROF_LINE_CONTEXT_SWITCH);
runcore->pprof_data[PPROF_DATA_LINE] = runcore->runloop_count;
runcore->pprof_data[PPROF_DATA_TIME] = 0;
runcore->pprof_data[PPROF_DATA_OPNAME] = (PPROF_DATA) "noop";
- record_values_ascii_pprof(runcore, PPROF_LINE_OP);
+ runcore->output_fn(runcore, PPROF_LINE_OP);
runcore->runloop_count++;
}
@@ -423,21 +457,21 @@
switch (type) {
case PPROF_LINE_CONTEXT_SWITCH:
{
- char *pnamespace = (char *) runcore->pprof_data[PPROF_DATA_NAMESPACE];
- char *pfilename = (char *) runcore->pprof_data[PPROF_DATA_FILENAME];
- void *sub_addr = (void *) runcore->pprof_data[PPROF_DATA_SUB_ADDR];
- void *ctx_addr = (void *) runcore->pprof_data[PPROF_DATA_CTX_ADDR];
+ char *pd_namespace = (char *) runcore->pprof_data[PPROF_DATA_NAMESPACE];
+ char *pd_filename = (char *) runcore->pprof_data[PPROF_DATA_FILENAME];
+ void *sub_addr = (void *) runcore->pprof_data[PPROF_DATA_SUB_ADDR];
+ void *ctx_addr = (void *) runcore->pprof_data[PPROF_DATA_CTX_ADDR];
fprintf(runcore->profile_fd,
- "OP:{x{ns:%s}x}{x{file:%s}x}{x{sub:%p}x}{x{ctx:%p}x}\n",
- pnamespace, pfilename, sub_addr, ctx_addr);
+ "CS:{x{ns:%s}x}{x{file:%s}x}{x{sub:%p}x}{x{ctx:%p}x}\n",
+ pd_namespace, pd_filename, sub_addr, ctx_addr);
}
break;
case PPROF_LINE_OP:
{
- PPROF_DATA line = (PPROF_DATA) runcore->pprof_data[PPROF_DATA_LINE];
- PPROF_DATA time = (PPROF_DATA) runcore->pprof_data[PPROF_DATA_TIME];
- char *opname = (char *) runcore->pprof_data[PPROF_DATA_OPNAME];
+ PPROF_DATA line = (PPROF_DATA) runcore->pprof_data[PPROF_DATA_LINE];
+ PPROF_DATA time = (PPROF_DATA) runcore->pprof_data[PPROF_DATA_TIME];
+ char *opname = (char *) runcore->pprof_data[PPROF_DATA_OPNAME];
fprintf(runcore->profile_fd, "OP:{x{line:%d}x}{x{time:%d}x}{x{op:%s}x}\n",
(int) line, (int) time, opname);
}
@@ -463,6 +497,25 @@
} /* switch */
}
+/*
+
+=item C<static void record_values_none(Parrot_profiling_runcore_t * runcore,
+Parrot_profiling_line type)>
+
+Accept data but don't actually write it anywhere.
+
+=cut
+
+*/
+
+static void
+record_values_none(ARGIN(Parrot_profiling_runcore_t * runcore),
+ARGIN_NULLOK(Parrot_profiling_line type))
+{
+ ASSERT_ARGS(record_values_none)
+ UNUSED(runcore);
+ UNUSED(type);
+}
/*
Modified: trunk/tools/dev/pprof2cg.pl
==============================================================================
--- trunk/tools/dev/pprof2cg.pl Tue Dec 8 05:15:45 2009 (r42937)
+++ trunk/tools/dev/pprof2cg.pl Tue Dec 8 08:17:41 2009 (r42938)
@@ -230,14 +230,14 @@
}
elsif ($line =~ /^VERSION:(\d+)$/) {
my $version = $1;
- if ($version != 1) {
+ if ($version != 2) {
die "profile was generated by an incompatible version of the profiling runcore.";
}
}
elsif ($line =~ /^CLI:(.*)$/) {
$stats->{'global_stats'}{'cli'} = $1;
}
- elsif ($line =~ /^END_OF_RUNLOOP$/) {
+ elsif ($line =~ /^END_OF_RUNLOOP:(.*)$/) {
# This is the end of an outermost runloop. Several of these can
# occur during the execution of a script, e.g. for :init subs.
@$call_stack = ();
More information about the parrot-commits
mailing list