Rprof: Enable Profiling of R's Execution

RprofR Documentation

Enable Profiling of R's Execution

Description

Enable or disable profiling of the execution of R expressions.

Usage

Rprof(filename = "Rprof.out", append = FALSE, interval = 0.02,
       memory.profiling = FALSE, gc.profiling = FALSE,
       line.profiling = FALSE, filter.callframes = FALSE,
       numfiles = 100L, bufsize = 10000L)

Arguments

filename

The file to be used for recording the profiling results. Set to NULL or "" to disable profiling.

append

logical: should the file be over-written or appended to?

interval

real: time interval between samples.

memory.profiling

logical: write memory use information to the file?

gc.profiling

logical: record whether GC is running?

line.profiling

logical: write line locations to the file?

filter.callframes

logical: filter out intervening call frames of the call tree. See the filtering out call frames section.

numfiles, bufsize

integers: line profiling memory allocation

Details

Enabling profiling automatically disables any existing profiling to another or the same file.

Profiling works by writing out the call stack every interval seconds, to the file specified. Either the summaryRprof function or the wrapper script R CMD Rprof can be used to process the output file to produce a summary of the usage; use R CMD Rprof --help for usage information.

How time is measured varies by platform:

On Windows:

Exactly what the time interval measures is subtle: it is time that the R process is running and executing an R command. It is not however just CPU time, for if readline() is waiting for input, that counts (on Windows, but not on a Unix-alike).

Note that the timing interval cannot be too small, for the time spent in each profiling step is added to the interval. What is feasible is machine-dependent, but 10ms seemed as small as advisable on a 1GHz machine.

On Unix-alikes

it is the CPU time of the R process, so for example excludes time when R is waiting for input or for processes run by system to return.

Note that the timing interval cannot usefully be too small: once the timer goes off, the information is not recorded until the next timing click (probably in the range 1–10 ms).

Functions will only be recorded in the profile log if they put a context on the call stack (see sys.calls). Some primitive functions do not do so: specifically those which are of type "special" (see the ‘R Internals’ manual for more details).

Individual statements will be recorded in the profile log if line.profiling is TRUE, and if the code being executed was parsed with source references. See parse for a discussion of source references. By default the statement locations are not shown in summaryRprof, but see that help page for options to enable the display.

Filtering Out Call Frames

Lazy evaluation makes the call stack more complex because intervening call frames are created between the time arguments are applied to a function, and the time they are effectively evaluated. When the call stack is represented as a tree, these intervening frames appear as sibling nodes. For instance, evaluating try(EXPR) produces the following call tree, at the time EXPR gets evaluated:

1. +-base::try(EXPR)
2. | \-base::tryCatch(...)
3. |   \-base:::tryCatchList(expr, classes, parentenv, handlers)
4. |     \-base:::tryCatchOne(expr, names, parentenv, handlers[[1L]])
5. |       \-base:::doTryCatch(return(expr), name, parentenv, handler)
6. \-EXPR

Lines 2 to 5 are intervening call frames, the last of which finally triggered evaluation of EXPR. Setting filter.callframes to TRUE simplifies the profiler output by removing all sibling nodes of intervening frames.

The same kind of call frame filtering is applied with eval() frames. When you call eval(), two frames are pushed on the stack to ensure a continuity between frames. Say we have these definitions:

calling <- function() evaluator(quote(called()), environment())
evaluator <- function(expr, env) eval(expr, env)
called <- function() EXPR()

calling() calls called() in its own environment, via eval(). The latter is called indirectly through evaluator(). The net effect of this code is identical to just calling called() directly, without the intermediaries. However, the full call stack looks like this:

1. calling()
2. \-evaluator(quote(called()), environment())
3.   \-base::eval(expr, env)
4.     \-base::eval(expr, env)
5.       \-called()
6.         \-EXPR()

When call frame filtering is turned on, the true calling environment of called() is looked up, and the filtered call stack looks like this:

1. calling()
5. \-called()
6.   \-EXPR()

If the calling environment is not on the stack, the function called by eval() becomes a root node. Say we have:

calling <- function() evaluator(quote(called()), new.env())

With call frame filtering we then get the following filtered call stack:

5. called()
6. \-EXPR()

Note

On Unix-alikes:

Profiling is not available on all platforms. By default, support for profiling is compiled in if possible – configure R with --disable-R-profiling to change this.

As R profiling uses the same mechanisms as C profiling, the two cannot be used together, so do not use Rprof in an executable built for C-level profiling.

On Windows:

filename can be a UTF-8-encoded filepath that cannot be translated to the current locale.

The profiler interrupts R asynchronously, and it cannot allocate memory to store results as it runs. This affects line profiling, which needs to store an unknown number of file pathnames. The numfiles and bufsize arguments control the size of pre-allocated buffers to hold these results: the former counts the maximum number of paths, the latter counts the numbers of bytes in them. If the profiler runs out of space it will skip recording the line information for new files, and issue a warning when Rprof(NULL) is called to finish profiling.

See Also

The chapter on “Tidying and profiling R code” in ‘Writing R Extensions’ (see the ‘doc/manual’ subdirectory of the R source tree).

summaryRprof to analyse the output file.

tracemem, Rprofmem for other ways to track memory use.

Examples

## Not run: Rprof()
## some code to be profiled
Rprof(NULL)
## some code NOT to be profiled
Rprof(append = TRUE)
## some code to be profiled
Rprof(NULL)
## ...
## Now post-process the output as described in Details

## End(Not run)