2

There are an array of approaches to measure function execution time in R (system.time(), microbenchmark(), proc.time(), profvis() etc) but they all involve wrapping these functions around your individual calls to time the process e.g.

system.time(a <- rnorm(10e7))  
#  user  system elapsed 
#   5.22    0.28    5.50 

This is fine when you know you want to time something in advance but as is often the case, I run a piece of code and realise that it has been running for sometime and I have forgotten to wrap it in a timer function above.

Is there a way to automatically time all calls? A crude estimate is all I am looking for. I suspect this is challenging so even printing the local time after every call would be useful (e.g. call format(Sys.time(), "%H:%M:%S") after each call). Is there a way to set this at a top level perhaps via .rprofile?

There is a similar type of question asked here. Although the solution posed by @hadley is useful it requires all your calls to be in a script and source()ed. The question and answer are quite old now and I am wondering are there any newer clever ways to do this. I am using RStudio in case its of relevance here.

Thanks

EDIT

@Allan Cameron makes a good point. I wouldn't want the start time printed for every function but at the top level only. So, if I ran the following chunk, I would just want one time printed (current time when the overall chunk was started) and not a separate one for group_by, summarise, n() etc.

#library(dplyr)
starwars %>%
  group_by(species) %>%
  summarise(
    n = n(),
    mass = mean(mass, na.rm = TRUE)
  ) %>%
  filter(
    n > 1,
    mass > 50
  )
user63230
  • 4,095
  • 21
  • 43
  • I don't think there's anything new. – user2554330 Nov 02 '21 at 12:58
  • In this type of scenario (say when I have to loop through a large but variable number of http requests), I get the function to print to the console after each loop giving the elapsed time. The problem with automatically printing after _every_ call is that many functions call functions which call functions, maybe hundreds per second, so you probably only want to time functions that are called from the top frame. But then, this doesn't help you if one function call is taking a long time because it contains a loop. Are you sure you want a print out after _every_ call? If not, what do you mean? – Allan Cameron Nov 02 '21 at 13:43
  • Just spitballing an idea here: you can start profiling (hit profile at the top, start profiling) and just end it when you want to see task duration or session ends by clicking red square on the top of your console window. This will produce a flame graph where you can zoom in on your actions, giving a rough estimate of the time there (this doesnt profile C code). What the effect on performance of your code is, or some other drawbacks, I don't know. – Donald Seinen Nov 02 '21 at 13:51
  • @AllanCameron You make a good point - I don't want current time printed for every call but rather for every chunk of code (see edit). I see how that can make the process more challenging to implement. Printing current time or elapsed time for a loop scenario is more straightforward. My updated question is can we automatically print current time at the start of a code chunk? – user63230 Nov 02 '21 at 14:26
  • If you are working in R studio, it is possible to use the rstudio API to set up a shortcut whereby you could run selected code with a printout of the start time. Would that work for you? – Allan Cameron Nov 02 '21 at 14:52
  • @DonaldSeinen I don't think that's of help here as its not an automated process – user63230 Nov 02 '21 at 16:00

1 Answers1

4

The following solution may work for you as long as you are using RStudio.

If you define the following function:

run_with_time <- function() {
  cat(date())
  rstudioapi::sendToConsole(
    unclass(rstudioapi::getSourceEditorContext()$selection)[[1]]$text)
}

Then whenever you run this function, the current time will be printed and whatever code is selected in your code editor in the IDE will be run in the console.

However, it would be inconvenient to have to type in a function call to do this, so it would be better to create a keyboard shortcut that runs this function. That way, you select the code block you want to run, press the keyboard shortcut and you have a time-stamped code block running in your console.

Getting the function to be called from a keyboard shortcut in RStudio is a bit involved, but can be done, for example using the shrtcts package. A description of how to do this is available here.

Allan Cameron
  • 147,086
  • 7
  • 49
  • 87
  • 1
    This is very clever and almost what I want. Instead of having to highlight or select the whole chunk of code I want to run, my RStudio shortcut to execute code is set up so that if the cursor is within the chunk, it will run the whole chunk. Is it possible to extend your code to this setting, I'm guessing that you might need to change "selection" in `getSourceEditorContext()$selection` to something else? I couldn't see anything in the `rstudioapi` help file, maybe not possible? – user63230 Nov 02 '21 at 15:56