Skip to content

Commit

Permalink
Add argument for profiling with real time intervals
Browse files Browse the repository at this point in the history
  • Loading branch information
lionel- committed Dec 7, 2020
1 parent fdf8792 commit be4d420
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 20 deletions.
4 changes: 2 additions & 2 deletions src/library/utils/R/Rprof.R
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
Rprof <- function(filename = "Rprof.out", append = FALSE, interval = 0.02,
memory.profiling = FALSE, gc.profiling = FALSE,
line.profiling = FALSE, filter.callframes = FALSE,
numfiles = 100L, bufsize = 10000L)
real.time = FALSE, numfiles = 100L, bufsize = 10000L)
{
if(is.null(filename)) filename <- ""
invisible(.External(C_Rprof, filename, append, interval, memory.profiling,
gc.profiling, line.profiling, filter.callframes,
numfiles, bufsize))
real.time, numfiles, bufsize))
}

Rprofmem <- function(filename = "Rprofmem.out", append = FALSE, threshold = 0)
Expand Down
6 changes: 6 additions & 0 deletions src/library/utils/man/Rprof.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ Rprof(filename = "Rprof.out", append = FALSE, interval = 0.02,
\item{line.profiling}{logical: write line locations to the file?}
\item{filter.callframes}{logical: filter out intervening call frames
of the call tree. See the filtering out call frames section.}
\item{real.time}{logical: whether to sample call stacks using real
time (also known as wall-clock time or elapsed time) or CPU time.
If your application is I/O bound, i.e. if it spends a lot of time
waiting for downloads, timers, or other similar operations to
complete, set `real.time` to `TRUE`. This type of interval is lower
precision so it is not the default.}
\item{numfiles, bufsize}{integers: line profiling memory allocation}
}
\details{
Expand Down
2 changes: 1 addition & 1 deletion src/library/utils/src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ static const R_ExternalMethodDef ExtEntries[] = {
EXTDEF(download, 6),
#endif
EXTDEF(unzip, 7),
EXTDEF(Rprof, 9),
EXTDEF(Rprof, 10),
EXTDEF(Rprofmem, 3),

EXTDEF(countfields, 6),
Expand Down
39 changes: 22 additions & 17 deletions src/main/eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ static int R_Profiling = 0;
/* A simple mechanism for profiling R code. When R_PROFILING is
enabled, eval will write out the call stack every PROFSAMPLE
microseconds using the SIGPROF handler triggered by timer signals
from the ITIMER_PROF timer. Since this is the same timer used by C
from the ITIMER_PROF timer by default. Since this is the same timer used by C
profiling, the two cannot be used together. Output is written to
the file PROFOUTNAME. This is a plain text file. The first line
of the file contains the value of PROFSAMPLE. The remaining lines
Expand Down Expand Up @@ -105,6 +105,8 @@ static size_t R_Srcfile_bufcount; /* how big is the array above
static SEXP R_Srcfiles_buffer = NULL; /* a big RAWSXP to use as a buffer for filenames and pointers to them */
static int R_Profiling_Error; /* record errors here */
static int R_Filter_Callframes = 0; /* whether to record only the trailing branch of call trees */
static int R_TimerType = ITIMER_PROF; /* type of timer to use: ITIMER_REAL or ITIMER_PROF (the default) */
static int R_SignalType = SIGPROF; /* type of signal to use: SIGALRM or SIGPROF (the default) */

#ifdef Win32
HANDLE MainThread;
Expand Down Expand Up @@ -342,7 +344,7 @@ static void doprof(int sig) /* sig is ignored in Windows */
fprintf(R_ProfileOutfile, "%s\n", buf);

#ifndef Win32
signal(SIGPROF, doprof);
signal(R_SignalType, doprof);
#endif /* not Win32 */

}
Expand All @@ -361,7 +363,7 @@ static void __cdecl ProfileThread(void *pwait)
#else /* not Win32 */
static void doprof_null(int sig)
{
signal(SIGPROF, doprof_null);
signal(R_SignalType, doprof_null);
}
#endif /* not Win32 */

Expand All @@ -378,8 +380,8 @@ static void R_EndProfiling(void)
itv.it_interval.tv_usec = 0;
itv.it_value.tv_sec = 0;
itv.it_value.tv_usec = 0;
setitimer(ITIMER_PROF, &itv, NULL);
signal(SIGPROF, doprof_null);
setitimer(R_TimerType, &itv, NULL);
signal(R_SignalType, doprof_null);

#endif /* not Win32 */
if(R_ProfileOutfile) fclose(R_ProfileOutfile);
Expand All @@ -397,7 +399,7 @@ static void R_EndProfiling(void)
static void R_InitProfiling(SEXP filename, int append, double dinterval,
int mem_profiling, int gc_profiling,
int line_profiling, int filter_callframes,
int numfiles, int bufsize)
int real_profiling, int numfiles, int bufsize)
{
#ifndef Win32
struct itimerval itv;
Expand Down Expand Up @@ -429,6 +431,8 @@ static void R_InitProfiling(SEXP filename, int append, double dinterval,
R_Line_Profiling = line_profiling;
R_GC_Profiling = gc_profiling;
R_Filter_Callframes = filter_callframes;
R_TimerType = real_profiling ? ITIMER_REAL : ITIMER_PROF;
R_SignalType = real_profiling ? SIGALRM : SIGPROF;

if (line_profiling) {
/* Allocate a big RAW vector to use as a buffer. The first len1 bytes are an array of pointers
Expand Down Expand Up @@ -458,13 +462,13 @@ static void R_InitProfiling(SEXP filename, int append, double dinterval,
error("profiling requires 'pthread' support");
#endif

signal(SIGPROF, doprof);
signal(R_SignalType, doprof);

itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = interval;
itv.it_value.tv_sec = 0;
itv.it_value.tv_usec = interval;
if (setitimer(ITIMER_PROF, &itv, NULL) == -1)
if (setitimer(R_TimerType, &itv, NULL) == -1)
R_Suicide("setting profile timer failed");
#endif /* not Win32 */
R_Profiling = 1;
Expand All @@ -474,7 +478,7 @@ SEXP do_Rprof(SEXP args)
{
SEXP filename;
int append_mode, mem_profiling, gc_profiling, line_profiling,
filter_callframes;
filter_callframes, real_profiling;
double dinterval;
int numfiles, bufsize;

Expand All @@ -492,7 +496,8 @@ SEXP do_Rprof(SEXP args)
mem_profiling = asLogical(CAR(args)); args = CDR(args);
gc_profiling = asLogical(CAR(args)); args = CDR(args);
line_profiling = asLogical(CAR(args)); args = CDR(args);
filter_callframes = asLogical(CAR(args)); args = CDR(args);
filter_callframes = asLogical(CAR(args)); args = CDR(args);
real_profiling = asLogical(CAR(args)); args = CDR(args);
numfiles = asInteger(CAR(args)); args = CDR(args);
if (numfiles < 0)
error(_("invalid '%s' argument"), "numfiles");
Expand All @@ -504,7 +509,7 @@ SEXP do_Rprof(SEXP args)
if (LENGTH(filename))
R_InitProfiling(filename, append_mode, dinterval, mem_profiling,
gc_profiling, line_profiling, filter_callframes,
numfiles, bufsize);
real_profiling, numfiles, bufsize);
else
R_EndProfiling();
return R_NilValue;
Expand Down Expand Up @@ -8265,7 +8270,7 @@ static void dobcprof(int sig)
{
if (current_opcode >= 0 && current_opcode < OPCOUNT)
opcode_counts[current_opcode]++;
signal(SIGPROF, dobcprof);
signal(R_SignalType, dobcprof);
}

SEXP do_bcprofstart(SEXP call, SEXP op, SEXP args, SEXP env)
Expand All @@ -8290,13 +8295,13 @@ SEXP do_bcprofstart(SEXP call, SEXP op, SEXP args, SEXP env)
for (i = 0; i < OPCOUNT; i++)
opcode_counts[i] = 0;

signal(SIGPROF, dobcprof);
signal(R_SignalType, dobcprof);

itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = interval;
itv.it_value.tv_sec = 0;
itv.it_value.tv_usec = interval;
if (setitimer(ITIMER_PROF, &itv, NULL) == -1)
if (setitimer(R_TimerType, &itv, NULL) == -1)
error(_("setting profile timer failed"));

bc_profiling = TRUE;
Expand All @@ -8306,7 +8311,7 @@ SEXP do_bcprofstart(SEXP call, SEXP op, SEXP args, SEXP env)

static void dobcprof_null(int sig)
{
signal(SIGPROF, dobcprof_null);
signal(R_SignalType, dobcprof_null);
}

SEXP do_bcprofstop(SEXP call, SEXP op, SEXP args, SEXP env)
Expand All @@ -8321,8 +8326,8 @@ SEXP do_bcprofstop(SEXP call, SEXP op, SEXP args, SEXP env)
itv.it_interval.tv_usec = 0;
itv.it_value.tv_sec = 0;
itv.it_value.tv_usec = 0;
setitimer(ITIMER_PROF, &itv, NULL);
signal(SIGPROF, dobcprof_null);
setitimer(R_TimerType, &itv, NULL);
signal(R_SignalType, dobcprof_null);

bc_profiling = FALSE;

Expand Down

0 comments on commit be4d420

Please sign in to comment.