Author: tim.bunce
Date: Tue Jun 30 07:28:26 2009
New Revision: 785
Modified:
trunk/Changes
trunk/NYTProf.xs
Log:
Record builtins, like sleep(), as having names begining with "CORE:"
(one colon) in the current package.
Added a few more opcode for pp_sysop_profiler to help demo/test it.
Fixed a bug with sub names containing colons :)
Replaced all use of warn() with new logwarn() that just does
vfprintf() to stderr, to fix infinite recursion via __WARN__.
Removed OpNAME(PL_op) from the DB_leave trace message because it seemed to
be
pointing to gibberish (freed memory?) in some cases, causing a core dump.
Renamed pp_leaving_profiler to pp_leave_profiler.
Modified: trunk/Changes
==============================================================================
--- trunk/Changes (original)
+++ trunk/Changes Tue Jun 30 07:28:26 2009
@@ -6,10 +6,15 @@
=head2 Changes in Devel::NYTProf 2.11
- Added treemap view of package and subroutine times, with drill-down.
+ Fixed risk of infinite recursion if trace enabled and
+ $SIG{__WARN__} was set to a code reference.
+
+ Added interactive treemap view of package and subroutine times.
+ Left-click to zoom in (drill-down) one level, right-click to zoom out.
Added sysops=1 option which enables profiling of perl opcodes
- that make potentially slow system calls.
+ that make potentially slow system calls. They appear as xsubs
+ in the current package with names prefixed by "CORE:".
XXX needs docs and more ops
=head2 Changes in Devel::NYTProf 2.10 (svn r774) 18th June 2009
Modified: trunk/NYTProf.xs
==============================================================================
--- trunk/NYTProf.xs (original)
+++ trunk/NYTProf.xs Tue Jun 30 07:28:26 2009
@@ -330,7 +330,7 @@
orig_ppaddr_t *PL_ppaddr_orig;
#define run_original_op(type) CALL_FPTR(PL_ppaddr_orig[type])(aTHX)
static OP *pp_entersub_profiler(pTHX);
-static OP *pp_leaving_profiler(pTHX);
+static OP *pp_leave_profiler(pTHX);
static HV *sub_callers_hv;
static HV *pkg_fids_hv; /* currently just package names */
@@ -339,6 +339,22 @@
#define getppid() 0
#endif
+static FILE *logfh;
+
+void
+logwarn(const char *pat, ...)
+{
+ /* we avoid using any perl mechanisms here */
+ va_list args;
+ va_start(args, pat);
+
+ if (!logfh)
+ logfh = stderr;
+ vfprintf(logfh, pat, args);
+
+ va_end(args);
+}
+
/***********************************
* Devel::NYTProf Functions *
@@ -812,7 +828,7 @@
Safefree(file);
if (ferror(raw_file))
- warn("There was an error writing to the profile data file\n");
+ logwarn("There was an error writing to the profile data file\n");
if (discard) {
/* close the underlying fd first so any buffered data gets
discarded
@@ -937,7 +953,7 @@
SvUTF8_on(sv);
if (trace_level >= 5)
- warn(" read string '%.*s'%s\n", (int)len, SvPV_nolen(sv),
+ logwarn(" read string '%.*s'%s\n", (int)len, SvPV_nolen(sv),
(SvUTF8(sv)) ? " (utf8)" : "");
return sv;
@@ -1131,7 +1147,7 @@
base_len = base_end - base_start;
if (trace_level >= 3)
- warn("find_autosplit_parent of '%.*s' (%s)\n",
+ logwarn("find_autosplit_parent of '%.*s' (%s)\n",
(int)base_len, base_start, file_name);
for ( ; e; e = (Hash_entry *)e->next_inserted) {
@@ -1140,7 +1156,7 @@
if (e->fid_flags & NYTP_FIDf_IS_AUTOSPLIT)
continue;
if (trace_level >= 4)
- warn("find_autosplit_parent: checking '%.*s'\n", e->key_len,
e->key);
+ logwarn("find_autosplit_parent: checking '%.*s'\n",
e->key_len, e->key);
/* skip if key is too small to match */
if (e->key_len < base_len)
@@ -1154,7 +1170,7 @@
continue;
if (trace_level >= 3)
- warn("matched autosplit '%.*s' to parent fid %d '%.*s'
(%c|%c)\n",
+ logwarn("matched autosplit '%.*s' to parent fid %d '%.*s'
(%c|%c)\n",
(int)base_len, base_start, e->id, e->key_len, e->key,
*(e_name-1),*sep);
match = e;
/* keep looking, so we'll return the most recently profiled match
*/
@@ -1188,8 +1204,8 @@
if (1 != hash_op(entry, &found, (bool)(created_via ? 1 : 0))) {
if (trace_level >= 4) {
if (found)
- warn("fid %d: %.*s\n", found->id, found->key_len,
found->key);
- else warn("fid -: %.*s HAS NO FID\n", entry.key_len,
entry.key);
+ logwarn("fid %d: %.*s\n", found->id, found->key_len,
found->key);
+ else logwarn("fid -: %.*s HAS NO FID\n", entry.key_len,
entry.key);
}
return (found) ? found->id : 0;
}
@@ -1207,7 +1223,7 @@
char *end = rninstr(file_name, file_name+file_name_len-1,
colon, colon+1);
if (!start || !end || start > end) { /* should never happen
*/
- warn("NYTProf unsupported filename syntax '%s'",
file_name);
+ logwarn("NYTProf unsupported filename syntax '%s'",
file_name);
return 0;
}
++start; /* move past [ */
@@ -1256,7 +1272,7 @@
--next_fid;
/* write a log message if tracing */
if (trace_level >= 2)
- warn("Use fid %2u (after %2u:%-4u) %x e%u:%u %.*s %s\n",
+ logwarn("Use fid %2u (after %2u:%-4u) %x e%u:%u %.*s %s\n",
found->id, last_executed_fid, last_executed_line,
found->fid_flags, found->eval_fid, found->eval_line_num,
found->key_len, found->key, (found->key_abs) ?
found->key_abs : "");
@@ -1286,7 +1302,7 @@
*/
if (!getcwd(file_name_abs, sizeof(file_name_abs))) {
/* eg permission */
- warn("getcwd: %s\n", strerror(errno));
+ logwarn("getcwd: %s\n", strerror(errno));
}
else {
#ifdef WIN32
@@ -1342,7 +1358,7 @@
if (trace_level >= 2) {
/* including last_executed_fid can be handy for tracking down how
* a file got loaded */
- warn("New fid %2u (after %2u:%-4u) 0x%02x e%u:%u %.*s %s %s,%s\n",
+ logwarn("New fid %2u (after %2u:%-4u) 0x%02x
e%u:%u %.*s %s %s,%s\n",
found->id, last_executed_fid, last_executed_line,
found->fid_flags, found->eval_fid, found->eval_line_num,
found->key_len, found->key, (found->key_abs) ?
found->key_abs : "",
@@ -1510,7 +1526,7 @@
}
if (!start_op) {
if (trace_level >= trace)
- warn("\tstart_cop_of_context: can't find start of %s\n",
+ logwarn("\tstart_cop_of_context: can't find start of %s\n",
block_type[CxTYPE(cx)]);
return NULL;
}
@@ -1519,14 +1535,14 @@
while ( o && (type = (o->op_type) ? o->op_type : (int)o->op_targ) ) {
if (type == OP_NEXTSTATE || type == OP_SETSTATE || type ==
OP_DBSTATE) {
if (trace_level >= trace)
- warn("\tstart_cop_of_context %s is %s line %d of %s\n",
+ logwarn("\tstart_cop_of_context %s is %s line %d of %s\n",
block_type[CxTYPE(cx)], OP_NAME(o),
(int)CopLINE((COP*)o),
OutCopFILE((COP*)o));
return (COP*)o;
}
/* should never get here but we do */
if (trace_level >= trace) {
- warn("\tstart_cop_of_context %s op '%s' isn't a cop",
+ logwarn("\tstart_cop_of_context %s op '%s' isn't a cop",
block_type[CxTYPE(cx)], OP_NAME(o));
if (trace_level > trace)
do_op_dump(1, PerlIO_stderr(), o);
@@ -1534,7 +1550,7 @@
o = o->op_next;
}
if (trace_level >= 3) {
- warn("\tstart_cop_of_context: can't find next cop for %s
line %ld\n",
+ logwarn("\tstart_cop_of_context: can't find next cop for %s
line %ld\n",
block_type[CxTYPE(cx)], (long)CopLINE(PL_curcop_nytprof));
do_op_dump(1, PerlIO_stderr(), start_op);
}
@@ -1553,7 +1569,7 @@
PERL_SI *top_si = PL_curstackinfo;
if (trace_level >= 6)
- warn("visit_contexts: \n");
+ logwarn("visit_contexts: \n");
while (1) {
/* we may be in a higher stacklevel, so dig down deeper */
@@ -1561,7 +1577,7 @@
/* callback should perhaps be moved to dopopcx_at */
while (cxix < 0 && top_si->si_type != PERLSI_MAIN) {
if (trace_level >= 6)
- warn("Not on main stack (type %d); digging top_si %p->%p,
ccstack %p->%p\n",
+ logwarn("Not on main stack (type %d); digging
top_si %p->%p, ccstack %p->%p\n",
(int)top_si->si_type, top_si, top_si->si_prev,
ccstack, top_si->si_cxstack);
top_si = top_si->si_prev;
ccstack = top_si->si_cxstack;
@@ -1570,12 +1586,12 @@
if (cxix < 0 || (cxix == 0 && !top_si->si_prev)) {
/* cxix==0 && !top_si->si_prev => top-level BLOCK */
if (trace_level >= 5)
- warn("visit_contexts: reached top of context stack\n");
+ logwarn("visit_contexts: reached top of context stack\n");
return NULL;
}
cx = &ccstack[cxix];
if (trace_level >= 5)
- warn("visit_context: %s cxix %d (si_prev %p)\n",
+ logwarn("visit_context: %s cxix %d (si_prev %p)\n",
block_type[CxTYPE(cx)], (int)cxix, top_si->si_prev);
if (callback(aTHX_ cx, &stop_at))
return cx;
@@ -1624,7 +1640,7 @@
if (trace_level >= 6) {
GV *sv = CvGV(cx->blk_sub.cv);
- warn("\tat %d: block %d sub %d for %s %s\n",
+ logwarn("\tat %d: block %d sub %d for %s %s\n",
last_executed_line, last_block_line, last_sub_line,
block_type[CxTYPE(cx)], (sv) ? GvNAME(sv) : "");
if (trace_level >= 9)
@@ -1636,7 +1652,7 @@
/* NULL, EVAL, LOOP, SUBST, BLOCK context */
if (trace_level >= 6)
- warn("\t%s\n", block_type[CxTYPE(cx)]);
+ logwarn("\t%s\n", block_type[CxTYPE(cx)]);
/* if we've got a block line, skip this context and keep looking for a
sub */
if (last_block_line)
@@ -1656,7 +1672,7 @@
}
/* shouldn't happen! */
if (trace_level >= 5)
- warn("at %d: %s in different file (%s, %s)",
+ logwarn("at %d: %s in different file (%s, %s)",
last_executed_line, block_type[CxTYPE(cx)],
OutCopFILE(near_cop), OutCopFILE(PL_curcop_nytprof));
return 1; /* stop looking */
@@ -1664,7 +1680,7 @@
last_block_line = CopLINE(near_cop);
if (trace_level >= 5)
- warn("\tat %d: block %d for %s\n",
+ logwarn("\tat %d: block %d for %s\n",
last_executed_line, last_block_line, block_type[CxTYPE(cx)]);
return 0;
}
@@ -1725,7 +1741,7 @@
get_ticks_between(start_time, end_time, elapsed, overflow);
}
if (overflow) /* XXX later output
overflow to file */
- warn("profile time overflow of %d seconds discarded", overflow);
+ logwarn("profile time overflow of %d seconds discarded", overflow);
reinit_if_forked(aTHX);
@@ -1740,7 +1756,7 @@
output_int(last_sub_line);
}
if (trace_level >= 4)
- warn("Wrote %d:%-4d %2u ticks (%u, %u)\n", last_executed_fid,
+ logwarn("Wrote %d:%-4d %2u ticks (%u, %u)\n",
last_executed_fid,
last_executed_line, elapsed, last_block_line,
last_sub_line);
}
@@ -1764,7 +1780,7 @@
/* op is null when called via finish_profile called by END */
if (!is_preamble && op) {
- warn("Unable to determine line number in %s",
OutCopFILE(cop));
+ logwarn("Unable to determine line number in %s",
OutCopFILE(cop));
if (trace_level > 5)
do_op_dump(1, PerlIO_stderr(), (OP*)cop);
}
@@ -1775,7 +1791,7 @@
file = OutCopFILE(cop);
if (!last_executed_fid) { /* first time */
if (trace_level >= 1) {
- warn("NYTProf pid %ld: first statement line %d of %s",
+ logwarn("NYTProf pid %ld: first statement line %d of %s",
(long)getpid(), (int)CopLINE(cop), OutCopFILE(cop));
}
}
@@ -1785,7 +1801,7 @@
}
if (trace_level >= 6)
- warn(" @%d:%-4d %s", last_executed_fid, last_executed_line,
+ logwarn(" @%d:%-4d %s", last_executed_fid, last_executed_line,
(profile_blocks) ? "looking for block and sub lines" : "");
if (profile_blocks) {
@@ -1854,9 +1870,9 @@
}
if (trace_level >= 4) {
- warn("left %u:%u via %s back to %s at %u:%u (b%u s%u) -
discounting next statement%s\n",
+ logwarn("left %u:%u back to %s at %u:%u (b%u s%u) - discounting
next statement%s\n",
prev_last_executed_fid, prev_last_executed_line,
- OP_NAME_safe(PL_op), OP_NAME_safe(op),
+ OP_NAME_safe(op),
last_executed_fid, last_executed_line, last_block_line,
last_sub_line,
(op) ? "" : ", LEAVING PERL"
);
@@ -1914,12 +1930,12 @@
}
} while (++opt_p < opt_end);
if (!found) {
- warn("Unknown NYTProf option: '%s'\n", option);
+ logwarn("Unknown NYTProf option: '%s'\n", option);
return;
}
}
if (trace_level)
- warn("# %s=%s\n", option, value);
+ logwarn("# %s=%s\n", option, value);
}
@@ -1964,7 +1980,7 @@
croak("Failed to open output '%s': %s%s", filename,
strerror(fopen_errno), hint);
}
if (trace_level)
- warn("Opened %s\n", filename);
+ logwarn("Opened %s\n", filename);
output_header(aTHX);
}
@@ -1985,7 +2001,7 @@
output_nv(gettimeofday_nv());
if (-1 == NYTP_close(out, 0))
- warn("Error closing profile data file: %s", strerror(errno));
+ logwarn("Error closing profile data file: %s", strerror(errno));
out = NULL;
}
@@ -1998,7 +2014,7 @@
/* we're now the child process */
if (trace_level >= 1)
- warn("New pid %d (was %d)\n", getpid(), last_pid);
+ logwarn("New pid %d (was %d)\n", getpid(), last_pid);
/* reset state */
last_pid = getpid();
@@ -2086,7 +2102,7 @@
}
if (trace_level >= 3)
- warn(" <- %s after %"NVff"s incl - %"NVff"s = %"NVff"s excl
(sub %g-%g=%g, oh %g-%g=%gt) d%d @%s\n",
+ logwarn(" <- %s after %"NVff"s incl - %"NVff"s = %"NVff"s excl
(sub %g-%g=%g, oh %g-%g=%gt) d%d @%s\n",
SvPV_nolen(subname_sv), incl_subr_sec, called_sub_secs,
excl_subr_sec,
cumulative_subr_secs, sub_call_start->current_subr_secs,
called_sub_secs,
cumulative_overhead_ticks,
sub_call_start->current_overhead_ticks, overhead_ticks,
@@ -2263,7 +2279,7 @@
sv_setpvf(subname_sv, "%s::%s", stash_name, GvNAME(gv));
}
else if (trace_level) {
- warn("I'm confused about CV %p", cv);
+ logwarn("I'm confused about CV %p", cv);
/* looks like Class::MOP doesn't give the CV GV stash a
name */
if (trace_level >= 2)
sv_dump((SV*)cv); /* coredumps in Perl_do_gvgv_dump,
looks line GvXPVGV is false, presumably on a Class::MOP wierdo sub */
@@ -2275,7 +2291,7 @@
if (!cv) {
/* should never get here as pp_entersub would have croaked
*/
const char *what = (is_xs) ? "xs" : "sub";
- warn("unknown entersub %s '%s'", what, SvPV_nolen(sub_sv));
+ logwarn("unknown entersub %s '%s'", what,
SvPV_nolen(sub_sv));
if (trace_level)
sv_dump(sub_sv);
sv_setpvf(subname_sv, "(unknown %s %s)", what,
SvPV_nolen(sub_sv));
@@ -2286,7 +2302,7 @@
sv_setpvf(subname_sv, "%s::__UNKNOWN__[0x%lx]",
(stash_name)?stash_name:"__UNKNOWN__", (unsigned
long)cv);
if (trace_level) {
- warn("unknown entersub %s assumed to be anon cv '%s'",
(is_xs) ? "xs" : "sub", SvPV_nolen(sub_sv));
+ logwarn("unknown entersub %s assumed to be anon
cv '%s'", (is_xs) ? "xs" : "sub", SvPV_nolen(sub_sv));
sv_dump(sub_sv);
}
}
@@ -2336,7 +2352,7 @@
SV *sv = *hv_fetch(GvHV(PL_DBsub), subname_pv,
(I32)SvCUR(subname_sv), 1);
sv_setpv(sv, ":0-0"); /* empty file name */
if (trace_level >= 2)
- warn("Adding fake DBsub entry for '%s' xsub\n",
subname_pv);
+ logwarn("Adding fake DBsub entry for '%s' xsub\n",
subname_pv);
}
}
}
@@ -2406,7 +2422,7 @@
static OP *
-pp_leaving_profiler(pTHX) /* handles OP_LEAVESUB,
OP_LEAVEEVAL, etc */
+pp_leave_profiler(pTHX) /* handles OP_LEAVESUB,
OP_LEAVEEVAL, etc */
{
OP *op = run_original_op(PL_op->op_type);
DB_leave(aTHX_ op);
@@ -2458,13 +2474,16 @@
int line = CopLINE(prev_cop);
char fid_line_key[50];
int fid_line_key_len;
- char *stash_name = "CORE::GLOBAL";
+ char *stash_name = CopSTASHPV(PL_curcop);
SV *subname_sv = newSV(0);
char *subname_pv;
SV *sv_tmp;
- /* XXX not quite right, but close enough for now */
- sv_setpvf(subname_sv, "%s::%s", stash_name, OP_NAME_safe(PL_op));
+ /* pretend builtins are in a ...::CORE:: subpackage of the current
+ * package. (We recklessly assume that won't clash with anything.)
+ * That's much more useful than putting them all in one place.
+ */
+ sv_setpvf(subname_sv, "%s::CORE:%s", stash_name,
OP_NAME_safe(PL_op));
subname_pv = SvPV_nolen(subname_sv);
fid = (file == last_executed_fileptr)
@@ -2499,7 +2518,7 @@
SV *sv = *hv_fetch(GvHV(PL_DBsub), subname_pv,
(I32)SvCUR(subname_sv), 1);
sv_setpv(sv, ":0-0"); /* empty file name */
if (trace_level >= 2)
- warn("Adding fake DBsub entry for '%s' sysop\n",
subname_pv);
+ logwarn("Adding fake DBsub entry for '%s' sysop\n",
subname_pv);
}
}
@@ -2547,7 +2566,7 @@
int prev_is_profiling = is_profiling;
if (trace_level)
- warn("NYTProf enable_profile (previously %s) to %s",
+ logwarn("NYTProf enable_profile (previously %s) to %s",
prev_is_profiling ? "enabled" : "disabled",
(file && *file) ? file : PROF_output_file);
@@ -2587,7 +2606,7 @@
is_profiling = 0;
}
if (trace_level)
- warn("NYTProf disable_profile (previously %s)",
+ logwarn("NYTProf disable_profile (previously %s)",
prev_is_profiling ? "enabled" : "disabled");
return prev_is_profiling;
}
@@ -2599,7 +2618,7 @@
int saved_errno = errno;
if (trace_level >= 1)
- warn("finish_profile (last_pid %d, getpid %d, overhead %"NVff"s,
is_profiling %d)\n",
+ logwarn("finish_profile (last_pid %d, getpid %d,
overhead %"NVff"s, is_profiling %d)\n",
last_pid, getpid(), cumulative_overhead_ticks/ticks_per_sec,
is_profiling);
/* write data for final statement, unless DB_leave has already */
@@ -2643,7 +2662,7 @@
/* downgrade to CLOCK_REALTIME if desired clock not available */
if (clock_gettime(profile_clock, &start_time) != 0) {
if (trace_level)
- warn("clock_gettime clock %d not available (%s) using
CLOCK_REALTIME instead",
+ logwarn("clock_gettime clock %d not available (%s) using
CLOCK_REALTIME instead",
profile_clock, strerror(errno));
profile_clock = CLOCK_REALTIME;
/* check CLOCK_REALTIME as well, just in case */
@@ -2653,7 +2672,7 @@
}
#else
if (profile_clock != -1) { /* user tried to select different clock */
- warn("clock %d not available (clock_gettime not supported on this
system)\n", profile_clock);
+ logwarn("clock %d not available (clock_gettime not supported on
this system)\n", profile_clock);
profile_clock = -1;
}
#endif
@@ -2668,11 +2687,11 @@
}
if (trace_level)
- warn("NYTProf init pid %d, clock %d%s\n", last_pid, profile_clock,
+ logwarn("NYTProf init pid %d, clock %d%s\n", last_pid,
profile_clock,
profile_zero ? ", zero=1" : "");
if (get_hv("DB::sub", 0) == NULL) {
- warn("NYTProf internal error - perl not in debug mode");
+ logwarn("NYTProf internal error - perl not in debug mode");
return 0;
}
@@ -2682,7 +2701,7 @@
if (!svp || !SvIOK(*svp)) croak("Time::HiRes is required");
u2time = INT2PTR(int(*)(pTHX_ UV*), SvIV(*svp));
if (trace_level)
- warn("Using Time::HiRes %p\n", u2time);
+ logwarn("Using Time::HiRes %p\n", u2time);
#endif
/* create file id mapping hash */
@@ -2701,17 +2720,17 @@
PL_ppaddr[OP_SETSTATE] = pp_stmt_profiler;
#endif
if (profile_leave) {
- PL_ppaddr[OP_LEAVESUB] = pp_leaving_profiler;
- PL_ppaddr[OP_LEAVESUBLV] = pp_leaving_profiler;
- PL_ppaddr[OP_LEAVE] = pp_leaving_profiler;
- PL_ppaddr[OP_LEAVELOOP] = pp_leaving_profiler;
- PL_ppaddr[OP_LEAVEWRITE] = pp_leaving_profiler;
- PL_ppaddr[OP_LEAVEEVAL] = pp_leaving_profiler;
- PL_ppaddr[OP_LEAVETRY] = pp_leaving_profiler;
- PL_ppaddr[OP_DUMP] = pp_leaving_profiler;
- PL_ppaddr[OP_RETURN] = pp_leaving_profiler;
+ PL_ppaddr[OP_LEAVESUB] = pp_leave_profiler;
+ PL_ppaddr[OP_LEAVESUBLV] = pp_leave_profiler;
+ PL_ppaddr[OP_LEAVE] = pp_leave_profiler;
+ PL_ppaddr[OP_LEAVELOOP] = pp_leave_profiler;
+ PL_ppaddr[OP_LEAVEWRITE] = pp_leave_profiler;
+ PL_ppaddr[OP_LEAVEEVAL] = pp_leave_profiler;
+ PL_ppaddr[OP_LEAVETRY] = pp_leave_profiler;
+ PL_ppaddr[OP_DUMP] = pp_leave_profiler;
+ PL_ppaddr[OP_RETURN] = pp_leave_profiler;
/* natural end of simple loop */
- PL_ppaddr[OP_UNSTACK] = pp_leaving_profiler;
+ PL_ppaddr[OP_UNSTACK] = pp_leave_profiler;
/* OP_NEXT is missing because that jumps to OP_UNSTACK */
/* OP_EXIT and OP_EXEC need special handling */
PL_ppaddr[OP_EXIT] = pp_exit_profiler;
@@ -2743,7 +2762,18 @@
chdir flock ioctl sleep syscall dump chroot
Perhaps make configurable. Could interate with Opcode module.
*/
+ /* XXX this will turn into a loop over an array that maps
+ * opcodes to the subname we'll use: OP_PRTF => "printf"
+ */
PL_ppaddr[OP_SLEEP] = pp_sysop_profiler;
+ PL_ppaddr[OP_OPEN] = pp_sysop_profiler;
+ PL_ppaddr[OP_CLOSE] = pp_sysop_profiler;
+ PL_ppaddr[OP_READ] = pp_sysop_profiler;
+ PL_ppaddr[OP_READLINE] = pp_sysop_profiler;
+ PL_ppaddr[OP_STAT] = pp_sysop_profiler;
+ PL_ppaddr[OP_OPEN_DIR] = pp_sysop_profiler;
+ PL_ppaddr[OP_CLOSEDIR] = pp_sysop_profiler;
+ PL_ppaddr[OP_READDIR] = pp_sysop_profiler;
}
/* redirect opcodes for caller tracking */
@@ -2844,8 +2874,10 @@
sub_pkg_filename_sv(pTHX_ char *sub_name)
{
SV **svp;
- char *colon = strrchr(sub_name, ':'); /* end of package name */
- if (!colon || colon == sub_name || *--colon != ':')
+ char *delim = "::";
+ /* find end of package name */
+ char *colon = rninstr(sub_name, sub_name+strlen(sub_name), delim,
delim+2);
+ if (!colon || colon == sub_name)
return Nullsv; /* no :: delimiter */
svp = hv_fetch(pkg_fids_hv, sub_name, (I32)(colon-sub_name), 0);
if (!svp)
@@ -2864,7 +2896,7 @@
unsigned int fid;
if (trace_level >= 2)
- warn("writing sub line ranges\n");
+ logwarn("writing sub line ranges\n");
/* Skim through PL_DBsub hash to build a package to filename hash
* by associating the package part of the sub_name in the key
@@ -2895,7 +2927,7 @@
fid = get_file_id(aTHX_ filename, filename_len, NYTP_FIDf_VIA_SUB);
if (trace_level >= 3)
- warn("Associating package of %s with %.*s (fid %d)\n",
+ logwarn("Associating package of %s with %.*s (fid %d)\n",
sub_name, (int)filename_len, filename, fid );
}
@@ -2912,7 +2944,7 @@
UV first_line, last_line;
if (!first || !last || !grok_number(first+1, last-first-1,
&first_line)) {
- warn("Can't parse %%DB::sub entry for %s '%s'\n", sub_name,
filename);
+ logwarn("Can't parse %%DB::sub entry for %s '%s'\n", sub_name,
filename);
continue;
}
last_line = atoi(++last);
@@ -2923,22 +2955,22 @@
if (!filename_len) { /* no filename, so presumably a fake entry
for xsub */
/* do we know a filename that contains subs in the same
package */
SV *pkg_filename_sv = sub_pkg_filename_sv(aTHX_ sub_name);
- if (SvOK(pkg_filename_sv)) {
+ if (pkg_filename_sv && SvOK(pkg_filename_sv)) {
filename = SvPV(pkg_filename_sv, filename_len);
if (trace_level >= 2)
- warn("Sub %s is xsub, we'll associate it with
filename %.*s\n", sub_name, (int)filename_len, filename);
+ logwarn("Sub %s is xsub, we'll associate it with
filename %.*s\n", sub_name, (int)filename_len, filename);
}
}
fid = get_file_id(aTHX_ filename, filename_len, 0);
if (!fid) {
if (trace_level >= 4)
- warn("Sub %s not profiled\n", sub_name);
+ logwarn("Sub %s not profiled\n", sub_name);
continue; /* no point in writing subs in files we've not
profiled */
}
if (trace_level >= 2)
- warn("Sub %s fid %u lines %lu..%lu\n",
+ logwarn("Sub %s fid %u lines %lu..%lu\n",
sub_name, fid, (unsigned long)first_line, (unsigned
long)last_line);
output_tag_int(NYTP_TAG_SUB_LINE_RANGE, fid);
@@ -2959,7 +2991,7 @@
if (!sub_callers_hv)
return;
if (trace_level >= 2)
- warn("writing sub callers\n");
+ logwarn("writing sub callers\n");
hv_iterinit(sub_callers_hv);
while (NULL != (fid_line_rvhv = hv_iternextsv(sub_callers_hv,
&sub_name, &sub_name_len))) {
@@ -2989,7 +3021,7 @@
output_str(sub_name, sub_name_len);
if (trace_level >= 3)
- warn("%s called by %u:%u: count %"NVff" (i%"NVff"s
e%"NVff"s u%"NVff"s s%"NVff"s, d%"NVff" ri%"NVff"s)\n",
+ logwarn("%s called by %u:%u: count %"NVff" (i%"NVff"s
e%"NVff"s u%"NVff"s s%"NVff"s, d%"NVff" ri%"NVff"s)\n",
sub_name, fid, line, sc[NYTP_SCi_CALL_COUNT],
sc[NYTP_SCi_INCL_RTIME], sc[NYTP_SCi_EXCL_RTIME],
sc[NYTP_SCi_INCL_UTIME], sc[NYTP_SCi_INCL_STIME],
@@ -3009,7 +3041,7 @@
long t_lines = 0;
if (trace_level >= 1)
- warn("writing file source code\n");
+ logwarn("writing file source code\n");
for (e = hashtable.first_inserted; e; e = (Hash_entry
*)e->next_inserted) {
I32 lines;
@@ -3019,13 +3051,13 @@
if ( !(e->fid_flags & NYTP_FIDf_HAS_SRC) ) {
++t_no_src;
if (src_av) /* sanity check */
- warn("fid %d has src but NYTP_FIDf_HAS_SRC not set!
(%.*s)",
+ logwarn("fid %d has src but NYTP_FIDf_HAS_SRC not set!
(%.*s)",
e->id, e->key_len, e->key);
continue;
}
if (!src_av) { /* sanity check */
++t_no_src;
- warn("fid %d has no src but NYTP_FIDf_HAS_SRC is set! (%.*s)",
+ logwarn("fid %d has no src but NYTP_FIDf_HAS_SRC is set!
(%.*s)",
e->id, e->key_len, e->key);
continue;
}
@@ -3038,7 +3070,7 @@
lines = av_len(src_av);
if (trace_level >= 4)
- warn("fid %d has %ld src lines", e->id, (long)lines);
+ logwarn("fid %d has %ld src lines", e->id, (long)lines);
/* for perl 5.10.0 or 5.8.8 (or earlier) use_db_sub is needed to
get src */
/* give a hint for the common case */
if (0 == lines && !use_db_sub
@@ -3058,13 +3090,13 @@
output_int(line);
output_str(src, (I32)len); /* includes newline */
if (trace_level >= 5)
- warn("fid %d src line %d: %s", e->id, line, src);
+ logwarn("fid %d src line %d: %s", e->id, line, src);
++t_lines;
}
}
if (trace_level >= 1)
- warn("wrote %ld source lines for %d files (%d skipped without
savesrc option, %d others had no source available)\n",
+ logwarn("wrote %ld source lines for %d files (%d skipped without
savesrc option, %d others had no source available)\n",
t_lines, t_save_src, t_has_src-t_save_src, t_no_src);
}
@@ -3152,7 +3184,7 @@
) {
++found;
if (trace_level >= 5)
- warn("found eval at '%s' in %s", src, start);
+ logwarn("found eval at '%s' in %s", src, start);
*dst++ = ' ';
*dst++ = '0';
src++; /* skip space */
@@ -3169,7 +3201,7 @@
*dst++ = '\0';
SvCUR_set(sv, strlen(start));
if (trace_level >= 5)
- warn("edited it to: %s", start);
+ logwarn("edited it to: %s", start);
}
return sv;
@@ -3210,7 +3242,7 @@
{
(void)hv_store(attr_hv, text, (I32)strlen(text), value_sv, 0);
if (trace_level >= 1)
- warn(": %s = '%s'\n", text, SvPV_nolen(value_sv));
+ logwarn(": %s = '%s'\n", text, SvPV_nolen(value_sv));
}
static int
@@ -3231,7 +3263,7 @@
if (!outer_fid)
return 0;
if (outer_fid == fid) {
- warn("Possible corruption: eval_outer_fid of %d is %d!\n", fid,
outer_fid);
+ logwarn("Possible corruption: eval_outer_fid of %d is %d!\n", fid,
outer_fid);
return 0;
}
if (eval_file_num_ptr)
@@ -3356,7 +3388,7 @@
}
if (trace_level >= 6)
- warn("Chunk %lu token is %d ('%c') at %ld%s\n",
input_chunk_seqn, c, c, NYTP_tell(in)-1, NYTP_type_of_offset(in));
+ logwarn("Chunk %lu token is %d ('%c') at %ld%s\n",
input_chunk_seqn, c, c, NYTP_tell(in)-1, NYTP_type_of_offset(in));
switch (c) {
case NYTP_TAG_DISCOUNT:
@@ -3370,9 +3402,9 @@
}
if (trace_level >= 4)
- warn("discounting next statement after %u:%d\n",
last_file_num, last_line_num);
+ logwarn("discounting next statement after %u:%d\n",
last_file_num, last_line_num);
if (statement_discount)
- warn("multiple statement discount after %u:%d\n",
last_file_num, last_line_num);
+ logwarn("multiple statement discount after %u:%d\n",
last_file_num, last_line_num);
++statement_discount;
++total_stmts_discounted;
break;
@@ -3417,7 +3449,7 @@
fid_info_rvav = *av_fetch(fid_fileinfo_av, file_num, 1);
if (!SvROK(fid_info_rvav)) { /* should never happen */
if (!SvOK(fid_info_rvav)) { /* only warn once */
- warn("Fid %u used but not defined", file_num);
+ logwarn("Fid %u used but not defined", file_num);
sv_setsv(fid_info_rvav, &PL_sv_no);
}
}
@@ -3434,7 +3466,7 @@
const char *new_file_name = "";
if (file_num != last_file_num && SvROK(fid_info_rvav))
new_file_name = SvPV_nolen(*av_fetch((AV
*)SvRV(fid_info_rvav), NYTP_FIDi_FILENAME, 1));
- warn("Read %d:%-4d %2u ticks%s %s\n",
+ logwarn("Read %d:%-4d %2u ticks%s %s\n",
file_num, line_num, ticks, trace_note,
new_file_name);
}
@@ -3462,7 +3494,7 @@
);
if (trace_level >= 3)
- warn("\tblock %u, sub %u\n", block_line_num,
sub_line_num);
+ logwarn("\tblock %u, sub %u\n", block_line_num,
sub_line_num);
}
total_stmts_measured++;
@@ -3511,7 +3543,7 @@
}
if (trace_level >= 2) {
- warn("Fid %2u is %s (eval %u:%u) 0x%x sz%u mt%u\n",
+ logwarn("Fid %2u is %s (eval %u:%u) 0x%x sz%u mt%u\n",
file_num, SvPV_nolen(filename_sv), eval_file_num,
eval_line_num,
fid_flags, file_size, file_mtime);
}
@@ -3526,7 +3558,7 @@
if (SvOK(*svp)) { /* should never happen, perhaps file is
corrupt */
AV *old_av = (AV *)SvRV(*av_fetch(fid_fileinfo_av,
file_num, 1));
SV *old_name = *av_fetch(old_av, 0, 1);
- warn("Fid %d redefined from %s to %s\n", file_num,
+ logwarn("Fid %d redefined from %s to %s\n", file_num,
SvPV_nolen(old_name), SvPV_nolen(filename_sv));
}
sv_setsv(*svp, rv);
@@ -3537,7 +3569,7 @@
/* this eval fid refers to the fid that contained the
eval */
SV *eval_fi = *av_fetch(fid_fileinfo_av,
eval_file_num, 1);
if (!SvROK(eval_fi)) { /* should never happen */
- warn("Eval '%s' (fid %d) has unknown invoking
fid %d\n",
+ logwarn("Eval '%s' (fid %d) has unknown invoking
fid %d\n",
SvPV_nolen(filename_sv), file_num,
eval_file_num);
/* so make it look like a real file instead of an
eval */
av_store(av, NYTP_FIDi_EVAL_FI, &PL_sv_undef);
@@ -3604,7 +3636,7 @@
av_store(file_av, line_num, src);
if (trace_level >= 4) {
- warn("Fid %2u:%u: %s\n", file_num, line_num,
SvPV_nolen(src));
+ logwarn("Fid %2u:%u: %s\n", file_num, line_num,
SvPV_nolen(src));
}
break;
}
@@ -3638,7 +3670,7 @@
subname_pv = SvPV(subname_sv, subname_len);
if (trace_level >= 2)
- warn("Sub %s fid %u lines %u..%u\n",
+ logwarn("Sub %s fid %u lines %u..%u\n",
subname_pv, fid, first_line, last_line);
av = lookup_subinfo_av(aTHX_ subname_sv, sub_subinfo_hv);
@@ -3648,7 +3680,7 @@
* for other cases.
*/
if (!instr(subname_pv, "__ANON__[(eval"))
- warn("Sub %s already defined!", subname_pv);
+ logwarn("Sub %s already defined!", subname_pv);
/* We could always discard the
fid+first_line+last_line here,
* because we already have them stored, but for
consistency
@@ -3717,7 +3749,7 @@
}
if (trace_level >= 3)
- warn("Sub %s called by fid %u line %u: count %d,
incl %f, excl %f, ucpu %f scpu %f\n",
+ logwarn("Sub %s called by fid %u line %u: count %d,
incl %f, excl %f, ucpu %f scpu %f\n",
SvPV_nolen(subname_sv), fid, line, count,
incl_time, excl_time, ucpu_time, scpu_time);
subinfo_av = lookup_subinfo_av(aTHX_ subname_sv,
sub_subinfo_hv);
@@ -3741,7 +3773,7 @@
if (!SvROK(sv)) /* autoviv */
sv_setsv(sv, newRV_noinc((SV*)newAV()));
else if
(!instr(SvPV_nolen(subname_sv), "__ANON__[(eval") || trace_level)
- warn("Merging extra sub caller info for %s %d:%d",
+ logwarn("Merging extra sub caller info
for %s %d:%d",
SvPV_nolen(subname_sv), fid, line);
av = (AV *)SvRV(sv);
sv = *av_fetch(av, NYTP_SCi_CALL_COUNT, 1);
@@ -3820,7 +3852,7 @@
(void)hv_store(live_pids_hv, text, len, newSVuv(ppid), 0);
if (trace_level)
- warn("Start of profile data for pid %s
(ppid %d, %"IVdf" pids live) at %"NVff"\n",
+ logwarn("Start of profile data for pid %s
(ppid %d, %"IVdf" pids live) at %"NVff"\n",
text, ppid, HvKEYS(live_pids_hv),
profiler_start_time);
store_attrib_sv(aTHX_ attr_hv, "profiler_start_time",
newSVnv(profiler_start_time));
@@ -3851,10 +3883,10 @@
}
if (!hv_delete(live_pids_hv, text, len, 0))
- warn("Inconsistent pids in profile data (pid %d not
introduced)",
+ logwarn("Inconsistent pids in profile data (pid %d not
introduced)",
pid);
if (trace_level)
- warn("End of profile data for pid %s (%"IVdf"
remaining) at %"NVff"\n", text,
+ logwarn("End of profile data for pid %s (%"IVdf"
remaining) at %"NVff"\n", text,
HvKEYS(live_pids_hv), profiler_end_time);
store_attrib_sv(aTHX_ attr_hv, "profiler_end_time",
newSVnv(profiler_end_time));
@@ -3875,7 +3907,7 @@
if ((NULL == (value = strchr(text, '=')))
|| (NULL == (end = strchr(text, '\n')))
) {
- warn("attribute malformed '%s'\n", text);
+ logwarn("attribute malformed '%s'\n", text);
continue;
}
*value++ = '\0';
@@ -3926,7 +3958,7 @@
}
if (trace_level >= 1)
- warn("# %s", text); /* includes \n */
+ logwarn("# %s", text); /* includes \n */
break;
}
@@ -3971,7 +4003,7 @@
}
if (HvKEYS(live_pids_hv)) {
- warn("profile data possibly truncated, no terminator for %"IVdf"
pids",
+ logwarn("profile data possibly truncated, no terminator
for %"IVdf" pids",
HvKEYS(live_pids_hv));
}
sv_free((SV*)live_pids_hv);
@@ -3988,7 +4020,7 @@
int show_summary_stats = (trace_level >= 1);
if (profiler_end_time && total_stmts_duration > profiler_duration
* 1.1) {
- warn("The sum of the statement timings is %.1f%% of the total
time profiling."
+ logwarn("The sum of the statement timings is %.1f%% of the
total time profiling."
" (Values slightly over 100%% can be due simply to
cumulative timing errors,"
" whereas larger values can indicate a problem with the
clock used.)\n",
total_stmts_duration / profiler_duration * 100);
@@ -3996,7 +4028,7 @@
}
if (show_summary_stats)
- warn("Summary: statements profiled %d (%d-%d), sum of
time %"NVff"s, profile spanned %"NVff"s\n",
+ logwarn("Summary: statements profiled %d (%d-%d), sum of
time %"NVff"s, profile spanned %"NVff"s\n",
total_stmts_measured-total_stmts_discounted,
total_stmts_measured, total_stmts_discounted,
total_stmts_duration,
profiler_end_time-profiler_start_time);
@@ -4114,7 +4146,7 @@
if (use_db_sub)
DB_stmt(aTHX_ NULL, PL_op);
else if (1||trace_level)
- warn("DB called needlessly");
+ logwarn("DB called needlessly");
void
set_option(const char *opt, const char *value)
@@ -4162,7 +4194,7 @@
else if (profile_start == NYTP_START_END) {
SV *enable_profile_sv = (SV *)get_cv("DB::enable_profile",
GV_ADDWARN);
if (trace_level >= 1)
- warn("enable_profile defered until END");
+ logwarn("enable_profile defered until END");
av_unshift(PL_endav, 1); /* we want to be first */
av_store(PL_endav, 0, SvREFCNT_inc(enable_profile_sv));
}
@@ -4184,7 +4216,7 @@
SV* cb;
CODE:
if (trace_level)
- warn("reading profile data from file %s\n", file);
+ logwarn("reading profile data from file %s\n", file);
in = NYTP_open(file, "rb");
if (in == NULL) {
croak("Failed to open input '%s': %s", file, strerror(errno));
--~--~---------~--~----~------------~-------~--~----~
You've received this message because you are subscribed to
the Devel::NYTProf Development User group.
Group hosted at: http://groups.google.com/group/develnytprof-dev
Project hosted at: http://perl-devel-nytprof.googlecode.com
CPAN distribution: http://search.cpan.org/dist/Devel-NYTProf
To post, email: [email protected]
To unsubscribe, email: [email protected]
-~----------~----~----~----~------~----~------~--~---