Skip to content

Instantly share code, notes, and snippets.

@hadley
Last active November 10, 2022 20:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hadley/48c396ae674cdccb618033df1b1ed671 to your computer and use it in GitHub Desktop.
Save hadley/48c396ae674cdccb618033df1b1ed671 to your computer and use it in GitHub Desktop.
f1 <- function(n) {
x <- numeric()
for (i in 1:n) {
x <- c(x, i)
}
x
}
f1.5 <- function(n) {
x <- numeric()
for (i in 1:n) {
x[[i]] <- i
}
x
}
f2 <- function(n) {
x <- numeric(n)
for (i in 1:n) {
x[[i]] <- i
}
x
}
bench::mark(f1(1e4), f1.5(1e4), f2(1e4))
#> Warning: Some expressions had a GC in every iteration; so filtering is disabled.
#> # A tibble: 3 × 6
#> expression min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
#> 1 f1(10000) 109ms 113.34ms 8.77 382MB 77.2
#> 2 f1.5(10000) 936µs 1.05ms 726. 1.68MB 67.6
#> 3 f2(10000) 212µs 216.77µs 4495. 96.77KB 6.00
@MVesuviusC
Copy link

MVesuviusC commented Nov 10, 2022

There are two differences between f1.5( ) and f2( ), so it's tricky to disentangle the difference caused by pre-allocation vs the use of [ ] vs [[ ]]. I added in the other comparisons and it does seem like pre-allocation makes things speed up a bit, though I admit I have no idea why.

append_x <- function(n) {
  x <- numeric()
  for (i in 1:n) {
    x <- c(x, i)
  }
  x
}

double_sq <- function(n) {
  x <- numeric()
  for (i in 1:n) {
    x[[i]] <- i
  }
  x
}

double_sq_pre <- function(n) {
  x <- numeric(n)
  for (i in 1:n) {
    x[[i]] <- i
  }
  x
}

single_sq_pre <- function(n) {
  x <- numeric(n)
  for (i in 1:n) {
    x[i] <- i
  }
  x
}

single_sq <- function(n) {
  x <- numeric()
  for (i in 1:n) {
    x[i] <- i
  }
  x
}

bench::mark(append_x(1e4),
            double_sq(1e4),
            single_sq(1e4),
            double_sq_pre(1e4),
            single_sq_pre(1e4)) |>
  dplyr::arrange(median)

# A tibble: 5 × 13
  expression                min   median `itr/sec` mem_alloc `gc/sec` n_itr
  <bch:expr>           <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl> <int>
1 single_sq_pre(10000) 567.64µs 593.79µs   1641.     78.17KB     2.00   821
2 double_sq_pre(10000) 573.76µs 601.22µs   1636.     78.17KB     2.00   818
3 double_sq(10000)       2.04ms   2.16ms    379.      1.66MB    29.9    190
4 single_sq(10000)       2.22ms   2.31ms    363.      1.66MB    31.8    183
5 append_x(10000)      141.69ms 158.73ms      6.40  381.96MB    51.2      4

@hadley
Copy link
Author

hadley commented Nov 10, 2022

I switched both to [[; as I'd expect, that made very little difference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment