Introduction

Jonathan Berrisch

2024-03-20

A Short Introduction to rcpptimer

This package provides a simple timer for Rcpp code. It is similar to the tictoc R package.

The Package wraps cpptimer which is a header only library that contains a class called CppTimer. ‘rcpptimer’ adds this class as Timer to the Rcpp namespace.

Basic usage of the Timer with Rcpp::cppFunction

With Rcpp::cppFunction we have to add the depends argument to the function. To tell the compiler that we want to link the ‘rcpptimer’ library to the ‘Rcpp’ code. That is, we can construct an instance if the Timer class and use the tic and toc methods to measure the time it takes to execute a function. Here, we just allocate some memory to have something to measure:

Rcpp::cppFunction('
int mem()
{
  Rcpp::Timer timer;
  timer.tic("mem");
  std::string s;
  s.reserve(1048576);
  timer.toc("mem");
  return(0);
}',
  depends = "rcpptimer"
)

mem()
#> [1] 0

print(times)
#>   Name Milliseconds SD Count
#> 1  mem        0.003  0     1

The results will be passed to the R environment as a dataframe named times. If you want to give the dataframe a different name you can pass that name to the constructor:

Rcpp::cppFunction('
int mem()
{
  Rcpp::Timer timer("mytimes");
  timer.tic("mem");
  std::string s;
  s.reserve(1048576);
  timer.toc("mem");
  return(0);
}',
  depends = "rcpptimer"
)

mem()
#> [1] 0

print(mytimes)
#>   Name Milliseconds SD Count
#> 1  mem        0.004  0     1

Warnings and how to disable them

The default setting will warn about timers that have not been stopped and toc calls for timers that have not yet been started using a matching call to tic:

Rcpp::cppFunction('
int mem()
{
  Rcpp::Timer timer;
  timer.tic("start");
  std::string s;
  timer.tic("reserve");
  s.reserve(1048576);
  timer.toc("reserve");
  timer.toc("finish");
  return(0);
}',
  depends = "rcpptimer"
)

mem()
#> Warning in mem(): Timer "finish" not started yet. 
#> Use tic("finish") to start the timer.
#> Warning in mem(): Timer "start" not stopped yet. 
#> Use toc("start") to stop the timer.
#> [1] 0

print(times)
#>      Name Milliseconds SD Count
#> 1 reserve        0.004  0     1

Note that this does not affect correctly terminated timers such as reserve. These warnings occur at runtime. Unfortunately, we can’t check for this at compile time since the tic and toc calls might spread over various functions so that (in some cases) we do not know the execution flow upfront.

However, if you are sure that you are using the timer correctly you can disable these warnings by passing false to the constructor:

Rcpp::cppFunction('
int mem()
{
  Rcpp::Timer timer(false); // Disable warnings
  timer.tic("start");
  std::string s;
  timer.tic("reserve");
  s.reserve(1048576);
  timer.toc("reserve");
  timer.toc("finish");
  return(0);
}',
  depends = "rcpptimer"
)

mem()
#> [1] 0

Rcpp::Timer::ScopedTimer

We offer an alternative to the tic-toc interface. The ScopedTimer lets you measure the time it takes for the object to go out of scope. We can adjust the above example to use the ScopedTimer instead:

Rcpp::cppFunction('
int mem()
{
  Rcpp::Timer timer;
  Rcpp::Timer::ScopedTimer scoped_timer(timer, "mem");
  std::string s;
  s.reserve(1048576);
  return(0);
}',
  depends = "rcpptimer"
)

mem()
#> [1] 0

print(times)
#>   Name Milliseconds SD Count
#> 1  mem        0.005  0     1

Note that you only need to initialize the ScopedTimer. Once it goes out of scope it will call timer.toc("mem") automatically.

We will add vignettes on how to use the package with Rcpp::sourceCpp and how to add it to your package soon.