Skip to content

Big speed up: Early return for vec_rep() and vec_rep_each() #1392

@mgirlich

Description

@mgirlich

The edge case times = 1 could be made much more efficient by returning early. Maybe also times = 0 could benefit a little from an early return. This creates nice speed ups e.g. in tidyr::expand_grid().

Benchmarks

library(vctrs)

x <- seq(10e6)
x[[1]] <- 1
vec_rep2 <- function(x, times) {
  if (times == 1L) {
    return(x)
  } else if (times == 0L) {
    vec_ptype(x)
  }
  
  vec_rep(x, times)
}

bench::mark(
  vec_rep = vec_rep(x, 1),
  vec_rep2 = vec_rep2(x, 1),
)
#> # A tibble: 2 x 6
#>   expression      min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 vec_rep      17.5ms     18ms      44.0     114MB     106.
#> 2 vec_rep2      382ns    451ns 1189079.         0B       0

bench::mark(
  vec_rep = vec_rep(x, 0),
  vec_rep2 = vec_rep2(x, 0),
)
#> # A tibble: 2 x 6
#>   expression      min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 vec_rep       819ns    907ns   795080.        0B      0  
#> 2 vec_rep2     1.93µs   2.12µs   396239.        0B     39.6

vec_rep_each2 <- function(x, times) {
  if (times == 1L) {
    return(x)
  } else if (times == 0L) {
    vec_ptype(x)
  }
  
  vec_rep_each(x, times)
}

bench::mark(
  vec_rep_each = vec_rep_each(x, 1),
  vec_rep_each2 = vec_rep_each2(x, 1),
)
#> # A tibble: 2 x 6
#>   expression         min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr>    <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 vec_rep_each    25.1ms   25.5ms      39.2     114MB     108.
#> 2 vec_rep_each2    413ns    445ns 1361489.         0B       0

bench::mark(
  vec_rep_each = vec_rep_each(x, 0),
  vec_rep_each2 = vec_rep_each2(x, 0),
)
#> # A tibble: 2 x 6
#>   expression         min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr>    <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 vec_rep_each    6.21ms    6.6ms      152.        0B        0
#> 2 vec_rep_each2   6.17ms   6.71ms      149.        0B        0

Created on 2021-06-16 by the reprex package (v2.0.0)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions