13.3 Report how much time each chunk takes to run
By default, knitr provides a text-based progress bar to show you the knitting progress. If you want more precise timing information about the chunks, you may register a custom chunk hook to record the time for each chunk. Here is an example hook:
::knit_hooks$set(time_it = local({
knitr<- NULL
now function(before, options) {
if (before) {
# record the current time before each chunk
<<- Sys.time()
now else {
} # calculate the time difference after a chunk
<- difftime(Sys.time(), now, units = "secs")
res # return a character string to show the time
paste("Time for this code chunk to run:", round(res,
2), "seconds")
}
} }))
Then you can time a chunk with the chunk option time_it
, e.g.,
```{r, time_it = TRUE}
Sys.sleep(2)
```
If you want to time all code chunks, you can certainly set the option globally: knitr::opts_chunk$set(time_it = TRUE)
.
In the above hook function, you can also output more information from the chunk options (i.e., the options
argument of the function). For example, you may print out the chunk label in the returned value:
paste("Time for the chunk", options$label, "to run:", res)
Or you may record the time without printing it out in the hook:
<- list() # store the time for each chunk
all_times ::knit_hooks$set(time_it = local({
knitr<- NULL
now function(before, options) {
if (before) {
<<- Sys.time()
now else {
} <- difftime(Sys.time(), now)
res $label]] <<- res
all_times[[options
}
} }))
Then you can access all the time information in the object all_times
. This object is a named list with the names being chunk labels, and element values being the execution time for each chunk.
Lastly, as a technical note, we want to explain the use of the local()
function in the previous hooks because some readers may not be familiar with it. This function allows you to run code in a “local” environment. The main benefit is that variables created in the code are local to that environment, so they will not pollute the outer environment (usually the global environment). For example, we created a variable now
in local()
, and used it in the time_it
hook function. In the hook function, we update the value of now
via the double arrow <<-
instead of the normal assignment operator <-
. This is because <<-
assigns a value to a variable in the parent environment (which is the environment in local()
in this case), and <-
can only assign values to variables in the current environment. Before each code chunk is evaluated, the local variable now
records the current time. After each code chunk is evaluated, we calculate the time difference between the current time and now
. Note that local()
returns the last value in the expression passed to it, which is a (hook) function in this case. In short, local()
can make your workspace cleaner by not exposing variables that are only used locally but unused in the global environment. If you do not mind creating a variable now
in the global environment, you can choose not to use local()
.