# Need help understanding the allocations

**URL:** https://discourse.julialang.org/t/need-help-understanding-the-allocations/104225
**Category:** Performance
**Tags:** question, memory-allocation
**Created:** [September 25, 2023, 1:56pm UTC](https://discourse.julialang.org/t/need-help-understanding-the-allocations/104225 "2023-09-25T13:56:39Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![navdeeprana](https://avatars.discourse-cdn.com/v4/letter/n/3da27b/32.png) [@navdeeprana](https://discourse.julialang.org/u/navdeeprana)
#### Post date: [September 25, 2023, 1:56pm UTC](https://discourse.julialang.org/t/need-help-understanding-the-allocations/104225/1 "2023-09-25T13:56:39Z")

</div>

Consider the following code

```julia
using BenchmarkTools
using Random
using QuadGK

f(p, xm, x) = -x^2 / ((p[1] - xm[1]*x)^2 + (p[2] - xm[2]*x)^2)
g(p, xm, x) = -x^2 / ((p[1] - xm[1])^2 + (p[2] - xm[2])^2)
integralf(p, xm) = quadgk(x -> f(p, xm, x), 0.0, 1.0)
integralg(p, xm) = quadgk(x -> g(p, xm, x), 0.0, 1.0)

function test(p, xm, integral)
    s = 0.0
    for i in 1:1000
        rand!(p)
        rand!(xm)
        res, err = integral(p, xm)
        s += res
    end
    return s
end
p = zeros(Float64, 2)
xm = zeros(Float64, 2)
test(p, xm, integralf)
test(p, xm, integralg)

```

When I run the benchmarks, `integralf` is allocating, whereas `integralg` ( which only has `x^2` in it) is not, which I do not understand.

`@benchmark test($p, $xm, $integralf)`

 ![image](https://global.discourse-cdn.com/julialang/original/3X/5/9/595f859f32dc4097df0e41a60ab5ec5ae535c000.png)

`@benchmark test($p, $xm, $integralg)`  
 ![image](https://global.discourse-cdn.com/julialang/original/3X/9/f/9fb0268f7506e003e554d2d4efcdab88df8d2039.png)

Can someone help me understanding what is going on?

EDIT: I think it is related to the fact that there are `1/(a-x)` kind of terms in the integrand, as shown by allocation profiler. With the division replaced by multiplication in `f(p, xm, x)`, it vanishes.

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [September 25, 2023, 4:07pm UTC](https://discourse.julialang.org/t/need-help-understanding-the-allocations/104225/2 "2023-09-25T16:07:00Z")

</div>

One thing is that you better define your test function like this:

```julia
julia> function test(p, xm, integral::F) where {F<:Function}
           s = 0.0
           for i in 1:1000
               rand!(p)
               rand!(xm)
               res, err = integral(p, xm)
               s += res
           end
           return s
       end

```

because Julia [by default may not specialize to function arguments](https://docs.julialang.org/en/v1/manual/performance-tips/#Be-aware-of-when-Julia-avoids-specializing), and this can cause allocations (although here you are using the function, so it should).

That being said, here this does not solve the problem. And since the direct call to each integral is not allocating, I think you reached some weird bug.

---

<div class="post-metadata">

### Author: ![skleinbo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skleinbo/32/36080_2.png) [@skleinbo](https://discourse.julialang.org/u/skleinbo)
#### Post date: [September 25, 2023, 5:15pm UTC](https://discourse.julialang.org/t/need-help-understanding-the-allocations/104225/3 "2023-09-25T17:15:04Z")

</div>

I believe the allocations come from the algorithm performing further subdivisions in the case of f, while it can early return for g, because the error estimate is sufficiently small already.

Step through it with Debugger and you’ll see what I mean.

---

<div class="post-metadata">

### Author: ![rveltz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rveltz/32/2707_2.png) [@rveltz](https://discourse.julialang.org/u/rveltz)
#### Post date: [September 25, 2023, 6:59pm UTC](https://discourse.julialang.org/t/need-help-understanding-the-allocations/104225/4 "2023-09-25T18:59:04Z")

</div>

Or use staticarrays

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [September 25, 2023, 8:40pm UTC](https://discourse.julialang.org/t/need-help-understanding-the-allocations/104225/5 "2023-09-25T20:40:41Z")

</div>

Running the integral functions outside the loop doesn’t allocate anything (can that be dependent on the random point given?)

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [September 25, 2023, 9:22pm UTC](https://discourse.julialang.org/t/need-help-understanding-the-allocations/104225/6 "2023-09-25T21:22:39Z")

</div>

It can be different. Quadgk is looking to see if the error bound is being met and that will be parameter dependent.

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [September 25, 2023, 9:51pm UTC](https://discourse.julialang.org/t/need-help-understanding-the-allocations/104225/7 "2023-09-25T21:51:42Z")

</div>

Indeed, sometimes it allocates, sometimes it doesn’t:

```julia
julia> @btime integralf($(rand(2)), $(rand(2)))
  55.014 ns (0 allocations: 0 bytes)
(-0.3320182264630196, 0.0)

julia> @btime integralf($(rand(2)), $(rand(2)))
  307.376 ns (2 allocations: 368 bytes)
(-2.1198229226184617, 9.467969463994308e-10)

julia> @btime integralf($(rand(2)), $(rand(2)))
  517.234 ns (2 allocations: 368 bytes)
(-4.848361174937609, 1.5858105731347827e-8)

julia> @btime integralf($(rand(2)), $(rand(2)))
  627.907 ns (2 allocations: 368 bytes)
(-18.88726883755866, 1.4078685466045737e-7)

julia> @btime integralf($(rand(2)), $(rand(2)))
  57.118 ns (0 allocations: 0 bytes)
(-0.4933392928396032, 7.264673307361136e-10)

```

> [@rveltz](#):
>
> Or use staticarrays

Does not work here:

```julia
julia> @btime integralf($(rand(SVector{2,Float64})), $(rand(SVector{2,Float64})))
  307.844 ns (2 allocations: 368 bytes)
(-2.7657212478611743, 4.964859356970663e-10)

```

---

<div class="post-metadata">

### Author: ![navdeeprana](https://avatars.discourse-cdn.com/v4/letter/n/3da27b/32.png) [@navdeeprana](https://discourse.julialang.org/u/navdeeprana)
#### Post date: [September 26, 2023, 8:46am UTC](https://discourse.julialang.org/t/need-help-understanding-the-allocations/104225/8 "2023-09-26T08:46:54Z")

</div>

Indeed as @skleinbo and @Oscar_Smith pointed out, it is because quadgk is using adaptive methods to meet the error bounds on the integral. The allocation profiler output also says so.

 ![image](https://global.discourse-cdn.com/julialang/original/3X/d/e/deac7d02df433532f1e93900de09071d1dfa6c70.png)

Changing the `rtol` parameter for `quadgk` changes the total allocations. Higher the `rtol`, lower the allocations for `integralf`.  
`integralf(p, xm) = quadgk(x -> f(p, xm, x), 0.0, 1.0, rtol=1.e-4)`  
`rtol=1.e-4 : Memory estimate: 112.02 KiB, allocs estimate: 609.`  
`rtol=1.e-2 : Memory estimate: 42.19 KiB, allocs estimate: 222.`

Is there a way to preallocate memory that quadgk can reuse? The integrand and the limits do not change, only the parameters `p` and `xm` do. I tried `segbuf` option but it increases the allocations.

---

<div class="post-metadata">

### Author: ![skleinbo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skleinbo/32/36080_2.png) [@skleinbo](https://discourse.julialang.org/u/skleinbo)
#### Post date: [September 26, 2023, 9:15am UTC](https://discourse.julialang.org/t/need-help-understanding-the-allocations/104225/9 "2023-09-26T09:15:25Z")

</div>

> [@navdeeprana](#):
>
> Is there a way to preallocate memory that quadgk can reuse?

Yes, you can pass that via the `segbuf` keyword. See the docstrings of `quadgk` and `alloc_segbuf` for how to do it.

However, I presume the algorithm is subdividing a lot because the integrand has a singularity, which may not be what you intend.
