mlr3pipelines
mlr3pipelines copied to clipboard
perf: improve scale performance by using min/max directly instead of range/diff
Using min/max directly compared to using range seems to be more performant, here a small benchmark and for reference the source code for range and diff explaining why its slower:
variant_a = function(x) {
rng = range(x, na.rm = TRUE, finite = TRUE)
(x - rng[1L]) / diff(rng)
}
variant_b = function(x) {
lower = min(x, na.rm = TRUE)
upper = max(x, na.rm = TRUE)
(x - lower) / (upper - lower)
}
res = suppressMessages(bench::press(
n = c(10L, 100L, 1000L, 10000L, 100000L),
{
x = rnorm(n)
bench::mark(
variant_a(x),
variant_b(x)
)
}
))
res
#> # A tibble: 10 × 7
#> expression n min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <int> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
#> 1 variant_a(x) 10 3.4µs 3.9µs 189430. 0B 37.9
#> 2 variant_b(x) 10 409.99ns 573.99ns 1321132. 0B 0
#> 3 variant_a(x) 100 4.06µs 4.76µs 189461. 4.63KB 37.9
#> 4 variant_b(x) 100 696.98ns 820ns 1041067. 848B 0
#> 5 variant_a(x) 1000 9.06µs 11.93µs 79220. 43.3KB 63.4
#> 6 variant_b(x) 1000 3.16µs 3.9µs 240959. 7.86KB 48.2
#> 7 variant_a(x) 10000 56.29µs 84.79µs 11643. 430.02KB 95.3
#> 8 variant_b(x) 10000 27.18µs 33.01µs 29087. 78.17KB 43.7
#> 9 variant_a(x) 100000 522.83µs 753.29µs 1322. 4.2MB 142.
#> 10 variant_b(x) 100000 268.35µs 324.84µs 3061. 781.3KB 48.7
Created on 2024-06-19 with reprex v2.1.0