# Anonymous function performance

**URL:** <https://discourse.julialang.org/t/anonymous-function-performance/81972>\
**Category:** Performance\
**Created:** [May 31, 2022, 9:59am UTC](https://discourse.julialang.org/t/anonymous-function-performance/81972 "2022-05-31T09:59:03Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![jerry\_ji](https://avatars.discourse-cdn.com/v4/letter/j/e36b37/32.png) [@jerry\_ji](https://discourse.julialang.org/u/jerry_ji)\
**Post date:** [May 31, 2022, 9:59am UTC](https://discourse.julialang.org/t/anonymous-function-performance/81972/1 "2022-05-31T09:59:03Z")

</div>

Hi all,  
Following code shows performance penalty associate with anonymous function. However the @code\_llvm shows both code is the same. Am I benchmark it in a wrong way?

* * *

using BenchmarkTools

f1(x)=5+6x

f2(x)=7+8x

f3(x)=9+10x

function f\_all(x)  
return f1(x)+f2(x)+f3(x)  
end

let  
macro\_f=eval(Meta.parse(“x-\>f1(x)+f2(x)+f3(x)”))  
@btime f\_all(rand(1:100))  
@btime macro\_f(rand(1:100))  
end

---

<div class="post-metadata">

**Author:** ![dawbarton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dawbarton/32/215461_2.png) [@dawbarton](https://discourse.julialang.org/u/dawbarton)\
**Post date:** [May 31, 2022, 10:43am UTC](https://discourse.julialang.org/t/anonymous-function-performance/81972/2 "2022-05-31T10:43:47Z")

</div>

Hi,

The problem appears to be that when you assign the anonymous function to a global variable and you have the penalties that apply to (non-const) globals. Named functions are `const` by-default.

Try

```julia
const macro_f=eval(Meta.parse("x->f1(x)+f2(x)+f3(x)"))

```

instead and you should see the time difference disappear. (BTW: quoting your code in triple backticks ```code``` makes it easier to read and paste into a Julia shell - the quotation marks in your code got mangled by whatever you used to paste in from.)

Hope that helps

---

<div class="post-metadata">

**Author:** ![dawbarton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dawbarton/32/215461_2.png) [@dawbarton](https://discourse.julialang.org/u/dawbarton)\
**Post date:** [May 31, 2022, 10:46am UTC](https://discourse.julialang.org/t/anonymous-function-performance/81972/3 "2022-05-31T10:46:43Z")

</div>

Another sidenote: I don’t know how you are constructing your anonymous functions but you’re usually better off constructing them from symbols rather than strings, e.g.,

```julia
const macro_f2 = eval(:(x -> f1(x) + f2(x) + f3(x)))

```

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [May 31, 2022, 10:48am UTC](https://discourse.julialang.org/t/anonymous-function-performance/81972/4 "2022-05-31T10:48:28Z")

</div>

But why construct the anonymous function with a macro at all? Why not just:

```julia
mf2 = x -> f1(x) + f2(x) + f3(x)

```

?

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [May 31, 2022, 10:49am UTC](https://discourse.julialang.org/t/anonymous-function-performance/81972/5 "2022-05-31T10:49:57Z")

</div>

This is a little bizarre actually. I initially thought of the common trap where `@btime ...` evaluates in the global scope, so it would use global variables if you didn’t `$`-interpolate values into the expression prior to evaluation. But `macro_f` is assigned in a local `let` block, so this fails to find a global `macro_f` and errors. I’m assuming OP previously defined a non-`const` global `macro_f` in the session, which has runtime costs as explained already. Even if there wasn’t a global `macro_f`, you could interpolate the local `macro_f`’s value for benchmarking `@btime $macro_f(rand(1:100))`, which has the same performance as `f_all`.

---

<div class="post-metadata">

**Author:** ![dawbarton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dawbarton/32/215461_2.png) [@dawbarton](https://discourse.julialang.org/u/dawbarton)\
**Post date:** [May 31, 2022, 10:52am UTC](https://discourse.julialang.org/t/anonymous-function-performance/81972/6 "2022-05-31T10:52:33Z")

</div>

Yes, I removed the let block to get it to work

---

<div class="post-metadata">

**Author:** ![jerry\_ji](https://avatars.discourse-cdn.com/v4/letter/j/e36b37/32.png) [@jerry\_ji](https://discourse.julialang.org/u/jerry_ji)\
**Post date:** [May 31, 2022, 12:55pm UTC](https://discourse.julialang.org/t/anonymous-function-performance/81972/7 "2022-05-31T12:55:09Z")

</div>

The final function consist of many terms based on user configuration. I don’t know if there is other way to construct the function at run time. I have tried sum the result from vector of function but it is not very performant.

---

<div class="post-metadata">

**Author:** ![jerry\_ji](https://avatars.discourse-cdn.com/v4/letter/j/e36b37/32.png) [@jerry\_ji](https://discourse.julialang.org/u/jerry_ji)\
**Post date:** [May 31, 2022, 1:03pm UTC](https://discourse.julialang.org/t/anonymous-function-performance/81972/8 "2022-05-31T13:03:17Z")

</div>

I’m trying to implement a time series model, which consist of configurable terms e.g. trend, seasonality, auto-regression etc. These terms is optional and operations among terms can be addition or multiplication.  
Is there any other performant way to achieve this?

---

<div class="post-metadata">

**Author:** ![dawbarton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dawbarton/32/215461_2.png) [@dawbarton](https://discourse.julialang.org/u/dawbarton)\
**Post date:** [May 31, 2022, 1:32pm UTC](https://discourse.julialang.org/t/anonymous-function-performance/81972/9 "2022-05-31T13:32:48Z")

</div>

I tend to do quite a bit of this - the most performant way is usually to build up the syntax tree directly, for example

```julia
expr = :(f1(x))
if some_option_is_true
    expr = :($expr + f2(x))
end
final_expr = :(x -> $expr)
func = eval(final_expr)

```

Alternatively, use something like ModelingToolkit.jl or Symbolics.jl directly. (They largely do the same thing under the hood with a few other bells-and-whistles.)

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [May 31, 2022, 1:50pm UTC](https://discourse.julialang.org/t/anonymous-function-performance/81972/10 "2022-05-31T13:50:19Z")

</div>

It’s generally better to construct the function definition and then eval the whole thing so that you get a constant binding automatically. If you want to store the function in a data structure this approach is fine though. You’ll get a dispatch hit at the first point you pass it as an argument but the function that actually calls the code will get specialized on it so that will be fast after the initial invocation.
