Skip to content

Commit

Permalink
add benchmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
pachadotdev committed Jan 1, 2025
1 parent 496dd6b commit 008ab7c
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 0 deletions.
20 changes: 20 additions & 0 deletions cpp11test/R/cpp11.R
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,26 @@ string_push_back_ <- function() {
.Call(`_cpp11test_string_push_back_`)
}

grow_strings_cpp11_ <- function(n, seed) {
.Call(`_cpp11test_grow_strings_cpp11_`, n, seed)
}

grow_strings_rcpp_ <- function(n, seed) {
.Call(`_cpp11test_grow_strings_rcpp_`, n, seed)
}

grow_strings_manual_ <- function(n, seed) {
.Call(`_cpp11test_grow_strings_manual_`, n, seed)
}

assign_cpp11_ <- function(n, seed) {
.Call(`_cpp11test_assign_cpp11_`, n, seed)
}

assign_rcpp_ <- function(n, seed) {
.Call(`_cpp11test_assign_rcpp_`, n, seed)
}

sum_dbl_for_ <- function(x) {
.Call(`_cpp11test_sum_dbl_for_`, x)
}
Expand Down
35 changes: 35 additions & 0 deletions cpp11test/bench/strings.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
pkgload::load_all("cpp11test")

bench::press(len = as.integer(10^(0:6)), {
bench::mark(
assign_cpp11_(n = len, 123L),
assign_rcpp_(n = len, 123L),
iterations = 20
)
})[c("expression", "len", "min", "mem_alloc", "n_itr", "n_gc")]

# Longer benchmark, lots of gc
len <- as.integer(10^7)
bench::mark(
cpp11 = cpp11_push_and_truncate_(len),
rcpp = rcpp_push_and_truncate_(len),
min_iterations = 200
)[c("expression", "min", "mem_alloc", "n_itr", "n_gc")]

bench::press(len = as.integer(10^(0:6)), {
bench::mark(
grow_strings_cpp11_(len, 123L),
grow_strings_rcpp_(len, 123L),
grow_strings_manual_(len, 123L),
iterations = 20
)
})[c("expression", "len", "min", "mem_alloc", "n_itr", "n_gc")]

# Longer benchmark, lots of gc
len <- as.integer(10^7)
bench::mark(
cpp11 = cpp11_grow_strings_(len),
rcpp = rcpp_grow_strings_(len),
manual = manual_grow_strings_(len),
min_iterations = 200
)[c("expression", "min", "mem_alloc", "n_itr", "n_gc")]
40 changes: 40 additions & 0 deletions cpp11test/src/cpp11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,41 @@ extern "C" SEXP _cpp11test_string_push_back_() {
return cpp11::as_sexp(string_push_back_());
END_CPP11
}
// strings.cpp
cpp11::strings grow_strings_cpp11_(size_t n, int seed);
extern "C" SEXP _cpp11test_grow_strings_cpp11_(SEXP n, SEXP seed) {
BEGIN_CPP11
return cpp11::as_sexp(grow_strings_cpp11_(cpp11::as_cpp<cpp11::decay_t<size_t>>(n), cpp11::as_cpp<cpp11::decay_t<int>>(seed)));
END_CPP11
}
// strings.cpp
Rcpp::CharacterVector grow_strings_rcpp_(size_t n, int seed);
extern "C" SEXP _cpp11test_grow_strings_rcpp_(SEXP n, SEXP seed) {
BEGIN_CPP11
return cpp11::as_sexp(grow_strings_rcpp_(cpp11::as_cpp<cpp11::decay_t<size_t>>(n), cpp11::as_cpp<cpp11::decay_t<int>>(seed)));
END_CPP11
}
// strings.cpp
SEXP grow_strings_manual_(size_t n, int seed);
extern "C" SEXP _cpp11test_grow_strings_manual_(SEXP n, SEXP seed) {
BEGIN_CPP11
return cpp11::as_sexp(grow_strings_manual_(cpp11::as_cpp<cpp11::decay_t<size_t>>(n), cpp11::as_cpp<cpp11::decay_t<int>>(seed)));
END_CPP11
}
// strings.cpp
cpp11::strings assign_cpp11_(size_t n, int seed);
extern "C" SEXP _cpp11test_assign_cpp11_(SEXP n, SEXP seed) {
BEGIN_CPP11
return cpp11::as_sexp(assign_cpp11_(cpp11::as_cpp<cpp11::decay_t<size_t>>(n), cpp11::as_cpp<cpp11::decay_t<int>>(seed)));
END_CPP11
}
// strings.cpp
Rcpp::CharacterVector assign_rcpp_(size_t n, int seed);
extern "C" SEXP _cpp11test_assign_rcpp_(SEXP n, SEXP seed) {
BEGIN_CPP11
return cpp11::as_sexp(assign_rcpp_(cpp11::as_cpp<cpp11::decay_t<size_t>>(n), cpp11::as_cpp<cpp11::decay_t<int>>(seed)));
END_CPP11
}
// sum.cpp
double sum_dbl_for_(cpp11::doubles x);
extern "C" SEXP _cpp11test_sum_dbl_for_(SEXP x) {
Expand Down Expand Up @@ -472,6 +507,8 @@ extern "C" {
extern SEXP run_testthat_tests(SEXP);

static const R_CallMethodDef CallEntries[] = {
{"_cpp11test_assign_cpp11_", (DL_FUNC) &_cpp11test_assign_cpp11_, 2},
{"_cpp11test_assign_rcpp_", (DL_FUNC) &_cpp11test_assign_rcpp_, 2},
{"_cpp11test_col_sums", (DL_FUNC) &_cpp11test_col_sums, 1},
{"_cpp11test_cpp11_add_vec_for_", (DL_FUNC) &_cpp11test_cpp11_add_vec_for_, 2},
{"_cpp11test_cpp11_insert_", (DL_FUNC) &_cpp11test_cpp11_insert_, 1},
Expand All @@ -488,6 +525,9 @@ static const R_CallMethodDef CallEntries[] = {
{"_cpp11test_gibbs_rcpp", (DL_FUNC) &_cpp11test_gibbs_rcpp, 2},
{"_cpp11test_gibbs_rcpp2", (DL_FUNC) &_cpp11test_gibbs_rcpp2, 2},
{"_cpp11test_grow_", (DL_FUNC) &_cpp11test_grow_, 1},
{"_cpp11test_grow_strings_cpp11_", (DL_FUNC) &_cpp11test_grow_strings_cpp11_, 2},
{"_cpp11test_grow_strings_manual_", (DL_FUNC) &_cpp11test_grow_strings_manual_, 2},
{"_cpp11test_grow_strings_rcpp_", (DL_FUNC) &_cpp11test_grow_strings_rcpp_, 2},
{"_cpp11test_my_message", (DL_FUNC) &_cpp11test_my_message, 2},
{"_cpp11test_my_message_n1", (DL_FUNC) &_cpp11test_my_message_n1, 1},
{"_cpp11test_my_message_n1fmt", (DL_FUNC) &_cpp11test_my_message_n1fmt, 1},
Expand Down
94 changes: 94 additions & 0 deletions cpp11test/src/strings.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
#include "cpp11/strings.hpp"
#include <random>
#include <vector>

#include <Rcpp.h>

// Test benchmark for string proxy assignment performance.
// We don't unwind_protect() before each `SET_STRING_ELT()` call,
Expand Down Expand Up @@ -33,3 +37,93 @@

return x;
}

// issue 406

std::random_device rd;
std::mt19937 gen(rd());

double random_double() {
std::uniform_real_distribution<double> dist(0.0, 1.0);
return dist(gen);
}

int random_int(int min, int max) {
std::uniform_int_distribution<int> dist(min, max);
return dist(gen);
}

std::string random_string() {
std::string s(10, '\0');
for (size_t i = 0; i < 10; i++) {
s[i] = random_int(0, 25) + 'a';
}
return s;
}

[[cpp11::register]] cpp11::strings grow_strings_cpp11_(size_t n, int seed) {
gen.seed(seed);
cpp11::writable::strings x;
for (size_t i = 0; i < n; ++i) {
x.push_back(random_string());
}
return x;
}

[[cpp11::register]] Rcpp::CharacterVector grow_strings_rcpp_(size_t n, int seed) {
gen.seed(seed);
Rcpp::CharacterVector x(n);
for (size_t i = 0; i < n; ++i) {
x[i] = random_string();
}
return x;
}

[[cpp11::register]] SEXP grow_strings_manual_(size_t n, int seed) {
gen.seed(seed);
SEXP data_ = PROTECT(Rf_allocVector(STRSXP, 0));
size_t size_ = 0;
size_t capacity_ = 0;
for (size_t i = 0; i < n; ++i) {
if (size_ == capacity_) {
capacity_ = capacity_ == 0 ? 1 : capacity_ * 2;
SEXP new_data_ = PROTECT(Rf_allocVector(STRSXP, capacity_));
for (size_t j = 0; j < size_; ++j) {
SET_STRING_ELT(new_data_, j, STRING_ELT(data_, j));
}
UNPROTECT(2);
data_ = PROTECT(new_data_);
}
SET_STRING_ELT(data_, size_++, Rf_mkChar(random_string().c_str()));
}
// copy back down to size
if (size_ < capacity_) {
SEXP new_data_ = PROTECT(Rf_allocVector(STRSXP, size_));
for (size_t j = 0; j < size_; ++j) {
SET_STRING_ELT(new_data_, j, STRING_ELT(data_, j));
}
UNPROTECT(2);
return new_data_;
} else {
UNPROTECT(1);
return data_;
}
}

[[cpp11::register]] cpp11::strings assign_cpp11_(size_t n, int seed) {
gen.seed(seed);
cpp11::writable::strings x(n);
for (size_t i = 0; i < n; ++i) {
x[i] = random_string();
}
return x;
}

[[cpp11::register]] Rcpp::CharacterVector assign_rcpp_(size_t n, int seed) {
gen.seed(seed);
Rcpp::CharacterVector x(n);
for (size_t i = 0; i < n; ++i) {
x[i] = random_string();
}
return x;
}

0 comments on commit 008ab7c

Please sign in to comment.