Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Computational Overhead Partial #715

Closed
karchjd opened this issue Oct 23, 2019 · 4 comments
Closed

Computational Overhead Partial #715

karchjd opened this issue Oct 23, 2019 · 4 comments
Labels
adverb 📚 bug an unexpected problem or unintended behavior

Comments

@karchjd
Copy link

karchjd commented Oct 23, 2019

partial seems to have a huge computational overhead. I guess you are aware of this and I am not using the package in an intended way but I thought I let you know anyway, since it was quite a surprise to me. A minimal working example demonstrating the problem is

library(tictoc)
library(purrr)
center <- function(x,myMean) return(x-myMean)
centerPartial <- partial(center,myMean=10)

reps <- 10^4
theData <- runif(100)

tic()
for (i in 1:reps){
  res <- center(theData,10)
}
toc()

tic()
for (i in 1:reps){
  res <- centerPartial(theData)
}
toc()

The second loop is around 100 times slower than the equivalent first loop.

@lionel- lionel- added bug an unexpected problem or unintended behavior adverb 📚 labels Jan 20, 2020
lionel- added a commit that referenced this issue Jul 29, 2020
Part of #715

fn <- partial(identity, 10)

```
bench::mark(
  application = identity(10),
  partial = fn()
)[1:8]
```

Before

```
  expression       min   median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc
  <bch:expr>  <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl> <int> <dbl>
1 application    236ns    306ns  2771144.        0B      0   10000     0
2 partial       11.1µs   13.6µs    70381.        0B     14.1  9998     2
```

After

```
  expression       min   median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc
  <bch:expr>  <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl> <int> <dbl>
1 application    251ns    301ns  2978820.        0B      0   10000     0
2 partial       3.64µs   4.66µs   202268.        0B     20.2  9999     1
```
@lionel-
Copy link
Member

lionel- commented Jul 29, 2020

rlang 0.4.7 reduced the performance gap. With 19c5bb2 this is further reduced to 15 times slower than normal function application:

fn <- partial(identity, 10)

bench::mark(
  application = identity(10),
  partial = fn()
)[1:8]

#> # Devel
#>   expression       min   median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc
#>   <bch:expr>  <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl> <int> <dbl>
#> 1 application    251ns    301ns  2978820.        0B      0   10000     0
#> 2 partial       3.64µs   4.66µs   202268.        0B     20.2  9999     1

#> # CRAN
#>   expression       min   median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc
#>   <bch:expr>  <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl> <int> <dbl>
#> 1 application    236ns    306ns  2771144.        0B      0   10000     0
#> 2 partial       11.1µs   13.6µs    70381.        0B     14.1  9998     2

@lionel-
Copy link
Member

lionel- commented Aug 5, 2020

I think it's now fast enough. partial() has a complicated implementation because it has a lot of constraints and cases to cover.

In general, you're probably better off using your own function wrappers in packages.

@lionel- lionel- closed this as completed Aug 5, 2020
@lionel- lionel- reopened this Aug 6, 2020
@lionel-
Copy link
Member

lionel- commented Aug 6, 2020

Reopening as I think we can fix this problem by abandoning support for a corner case (dots coming from multiple environments).

@lionel- lionel- closed this as completed in 308dbe0 Aug 6, 2020
@lionel-
Copy link
Member

lionel- commented Aug 6, 2020

I solved this by using a simpler approach when the arguments are all evaluated in the same environment, which is the common case. This completely removes the overhead:

wrapper <- function() identity(10)
fn <- partial(identity, 10)

bench::mark(
  wrapper = wrapper(),
  partial = fn()
)[1:8]
#> + + + # A tibble: 2 x 8
#>   expression      min   median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc
#>   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl> <int> <dbl>
#> 1 wrapper       344ns    428ns  2103432.        0B        0 10000     0
#> 2 partial       450ns    577ns  1566484.        0B        0 10000     0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
adverb 📚 bug an unexpected problem or unintended behavior
Projects
None yet
Development

No branches or pull requests

2 participants