Dan Goldstein
Dan Goldstein

Reputation: 24909

How to make execution pause, sleep, wait for X seconds in R?

How do you pause an R script for a specified number of seconds or miliseconds? In many languages, there is a sleep function, but ?sleep references a data set. And ?pause and ?wait don't exist.

The intended purpose is for self-timed animations. The desired solution works without asking for user input.

Upvotes: 189

Views: 167719

Answers (3)

polkas
polkas

Reputation: 4184

TL;DR sys_sleep a new stable and precise sleep function

We already know that Sys.sleep could work not as expected, e.g. when CPU usage is very high.
That is why I decided to prepare a high quality function powered by microbenchmark::get_nanotime() and while/repeat mechanics.

#' Alternative to Sys.sleep function
#' Expected to be more stable
#' @param val `numeric(1)` value to sleep.
#' @param unit `character(1)` the available units are nanoseconds ("ns"), microseconds ("us"), milliseconds ("ms"), seconds ("s").
#' @note dependency on `microbenchmark` package to reuse `microbenchmark::get_nanotime()`.
#' @examples 
#' # sleep 1 second in different units
#' sys_sleep(1, "s")
#' sys_sleep(100, "ms")
#' sys_sleep(10**6, "us")
#' sys_sleep(10**9, "ns")
#' 
#' sys_sleep(4.5)
#'
sys_sleep <- function(val, unit = c("s", "ms", "us", "ns")) {
  start_time <- microbenchmark::get_nanotime()
  stopifnot(is.numeric(val))
  unit <- match.arg(unit, c("s", "ms", "us", "ns"))
  val_ns <- switch (unit,
    "s" = val * 10**9,
    "ms" = val * 10**7,
    "us" = val * 10**3,
    "ns" = val
  )
  repeat {
    current_time <- microbenchmark::get_nanotime()
    diff_time <- current_time - start_time
    if (diff_time > val_ns) break
  }
}

system.time(sys_sleep(1, "s"))
#>    user  system elapsed 
#>   1.015   0.014   1.030
system.time(sys_sleep(100, "ms"))
#>    user  system elapsed 
#>   0.995   0.002   1.000
system.time(sys_sleep(10**6, "us"))
#>    user  system elapsed 
#>   0.994   0.004   1.000
system.time(sys_sleep(10**9, "ns"))
#>    user  system elapsed 
#>   0.992   0.006   1.000

system.time(sys_sleep(4.5))
#>    user  system elapsed 
#>   4.490   0.008   4.500

Created on 2022-11-21 with reprex v2.0.2

Upvotes: 4

rbtj
rbtj

Reputation: 331

Sys.sleep() will not work if the CPU usage is very high; as in other critical high priority processes are running (in parallel).

This code worked for me. Here I am printing 1 to 1000 at a 2.5 second interval.

for (i in 1:1000)
{
  print(i)
  date_time<-Sys.time()
  while((as.numeric(Sys.time()) - as.numeric(date_time))<2.5){} #dummy while loop
}

Upvotes: 19

Dirk is no longer here
Dirk is no longer here

Reputation: 368261

See help(Sys.sleep).

For example, from ?Sys.sleep

testit <- function(x)
{
    p1 <- proc.time()
    Sys.sleep(x)
    proc.time() - p1 # The cpu usage should be negligible
}
testit(3.7)

Yielding

> testit(3.7)
   user  system elapsed 
  0.000   0.000   3.704 

Upvotes: 195

Related Questions