Glue is advertised as
Fast, dependency free string literals
So what do we mean when we say that glue is fast? This does not mean glue is the fastest thing to use in all cases, however for the features it provides we can confidently say it is fast.
A good way to determine this is to compare its speed of execution to some alternatives.
-
base::paste0(),base::sprintf(): Functions in base R implemented in C that provide variable insertion (but not interpolation). -
R.utils::gstring(): Provides a similar interface as glue, but uses${}to delimit blocks to interpolate. -
pystr::pystr_format()1,rprintf::rprintf(): Provide an interface similar to python string formatters with variable replacement, but not arbitrary interpolation.
Note: stringr::str_interp() was previously included in this benchmark, but is now formally marked as “superseded”, in favor of stringr::str_glue(), which just calls glue::glue().
Simple concatenation
bar <- "baz"
simple <- bench::mark(
glue = as.character(glue::glue("foo{bar}")),
gstring = R.utils::gstring("foo${bar}"),
paste0 = paste0("foo", bar),
sprintf = sprintf("foo%s", bar),
rprintf = rprintf::rprintf("foo$bar", bar = bar)
)
simple |>
select(expression:total_time) |>
arrange(median)
#> # A tibble: 5 × 6
#> expression min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
#> 1 sprintf 721.08ns 772.1ns 1188771. 0B 0
#> 2 paste0 1.39µs 1.5µs 627136. 0B 0
#> 3 glue 93.44µs 99.2µs 9648. 141.56KB 10.3
#> 4 gstring 216.8µs 228.3µs 4276. 2.46MB 6.11
#> 5 rprintf 273.86µs 284.5µs 3440. 504.02KB 4.05
# plotting function defined in a hidden chunk
plot_comparison(simple)
While glue() is slower than paste0 and sprintf(), it is twice as fast as gstring(), and rprintf().
Although paste0() and sprintf() don’t do string interpolation and will likely always be significantly faster than glue, glue was never meant to be a direct replacement for them.
rprintf::rprintf() does only variable interpolation, not arbitrary expressions, which was one of the explicit goals of writing glue.
So glue is ~2x as fast as the function (gstring()), which has roughly equivalent functionality.
It also is still quite fast, with over 8000 evaluations per second on this machine.
Vectorized performance
Taking advantage of glue’s vectorization is the best way to improve performance. In a vectorized form of the previous benchmark, glue’s performance is much closer to that of paste0() and sprintf().
bar <- rep("bar", 1e5)
vectorized <- bench::mark(
glue = as.character(glue::glue("foo{bar}")),
gstring = R.utils::gstring("foo${bar}"),
paste0 = paste0("foo", bar),
sprintf = sprintf("foo%s", bar),
rprintf = rprintf::rprintf("foo$bar", bar = bar)
)
vectorized |>
select(expression:total_time) |>
arrange(median)
#> # A tibble: 5 × 6
#> expression min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
#> 1 paste0 8.35ms 8.38ms 119. 781.3KB 4.17
#> 2 sprintf 8.39ms 8.46ms 117. 781.3KB 4.17
#> 3 gstring 11.33ms 11.43ms 84.3 1.53MB 4.22
#> 4 glue 12.62ms 12.96ms 76.7 2.29MB 6.58
#> 5 rprintf 28.76ms 29.03ms 32.2 3.05MB 4.60
# plotting function defined in a hidden chunk
plot_comparison(vectorized)
