Skip to content

Conversation

@DavisVaughan
Copy link
Member

@DavisVaughan DavisVaughan commented Oct 17, 2025

Two wins:

  • Using list2() to avoid the allocation that came with rlang_env_dots_list()
  • That still wasn't enough, because vec_recycle_common() was cloning as well, even in the no-op case! So I switched it to be smart enough to return the object unchanged if no recycling is required for any element.
pkgs <- tibble::tribble(
  ~vctrs             , ~rlang        ,
  "vctrs"            , "rlang"       ,
  "r-lib/vctrs#2070" , "r-lib/rlang" ,
)

# Just no-op recycle
cross::bench_versions(pkgs = pkgs, {
  library(vctrs)
  x <- as.list(1:1e6)
  bench::mark(vec_recycle_common(!!!x, .size = 1))
})
#> # A tibble: 2 × 7
#>   pkg                      expression    min median `itr/sec` mem_alloc `gc/sec`
#>   <chr>                    <bch:expr> <bch:> <bch:>     <dbl> <bch:byt>    <dbl>
#> 1 vctrs, rlang             vec_recyc…   38ms   38ms      26.3    7.63MB     316.
#> 2 r-lib/vctrs#2070, r-lib… vec_recyc… 10.9ms 11.3ms      87.1    3.06KB       0

# No-op recycle and size determination
cross::bench_versions(pkgs = pkgs, {
  library(vctrs)
  x <- as.list(1:1e6)
  bench::mark(vec_recycle_common(!!!x))
})
#> # A tibble: 2 × 7
#>   pkg                    expression     min  median `itr/sec` mem_alloc `gc/sec`
#>   <chr>                  <bch:expr> <bch:t> <bch:t>     <dbl> <bch:byt>    <dbl>
#> 1 vctrs, rlang           vec_recyc… 146.1ms 150.1ms      6.39    7.63MB     27.1
#> 2 r-lib/vctrs#2070, r-l… vec_recyc…  23.9ms  25.1ms     39.7     3.27KB      0

# Recycle to known size
cross::bench_versions(pkgs = pkgs, {
  library(vctrs)
  x <- as.list(1:1e6)
  x <- c(x, list(1:2))
  bench::mark(vec_recycle_common(!!!x, .size = 2), iterations = 10)
})
#> # A tibble: 2 × 7
#>   pkg                    expression     min  median `itr/sec` mem_alloc `gc/sec`
#>   <chr>                  <bch:expr> <bch:t> <bch:t>     <dbl> <bch:byt>    <dbl>
#> 1 vctrs, rlang           vec_recyc… 182.9ms 346.4ms      2.65    7.63MB     6.36
#> 2 r-lib/vctrs#2070, r-l… vec_recyc…  94.3ms  95.3ms      7.87    7.63MB     9.44

# Recycle and size determination
cross::bench_versions(pkgs = pkgs, {
  library(vctrs)
  x <- as.list(1:1e6)
  x <- c(x, list(1:2))
  bench::mark(vec_recycle_common(!!!x), iterations = 10)
})
#> # A tibble: 2 × 7
#>   pkg                       expression   min median `itr/sec` mem_alloc `gc/sec`
#>   <chr>                     <bch:expr> <bch> <bch:>     <dbl> <bch:byt>    <dbl>
#> 1 vctrs, rlang              vec_recyc… 273ms  492ms      2.09    7.63MB     9.40
#> 2 r-lib/vctrs#2070, r-lib/… vec_recyc… 109ms  113ms      6.86    7.63MB     8.24

@DavisVaughan DavisVaughan merged commit b7fa892 into main Oct 17, 2025
14 checks passed
@DavisVaughan DavisVaughan deleted the feature/vec-recycle-common-improvements branch October 17, 2025 19:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants