# Memory on array element assignment

**URL:** https://discourse.julialang.org/t/memory-on-array-element-assignment/85069
**Category:** Performance
**Created:** [July 31, 2022, 4:46pm UTC](https://discourse.julialang.org/t/memory-on-array-element-assignment/85069 "2022-07-31T16:46:00Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![RainerHeintzmann](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rainerheintzmann/32/19726_2.png) [@RainerHeintzmann](https://discourse.julialang.org/u/RainerHeintzmann)
#### Post date: [July 31, 2022, 4:46pm UTC](https://discourse.julialang.org/t/memory-on-array-element-assignment/85069/1 "2022-07-31T16:46:00Z")

</div>

I am writing some sort of histogramming function and am having trouble with bad performance due to dynamic allocations in each assignment. It boils down to the following simple problem:

```julia
julia> a=zeros(UInt16,1000000);

julia> @time for n=1:size(a,1); a[n]=mod(n,10);end
  0.169991 seconds (3.00 M allocations: 61.067 MiB, 52.07% gc time, 1.82% compilation time)

julia> @time for n=1:1000000; a[n]=mod(n,10);end
  0.022683 seconds (999.49 k allocations: 15.251 MiB)

```

Is there a way to avoid the 3 Million allocations in the middle example?

---

<div class="post-metadata">

### Author: ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)
#### Post date: [July 31, 2022, 4:57pm UTC](https://discourse.julialang.org/t/memory-on-array-element-assignment/85069/2 "2022-07-31T16:57:21Z")

</div>

Seems like you’re just seeing the usual performance issues with global variables: [Performance Tips · The Julia Language](https://docs.julialang.org/en/v1/manual/performance-tips/#Performance-critical-code-should-be-inside-a-function)

What happens if you avoid global variables?

---

<div class="post-metadata">

### Author: ![RainerHeintzmann](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rainerheintzmann/32/19726_2.png) [@RainerHeintzmann](https://discourse.julialang.org/u/RainerHeintzmann)
#### Post date: [July 31, 2022, 5:33pm UTC](https://discourse.julialang.org/t/memory-on-array-element-assignment/85069/3 "2022-07-31T17:33:31Z")

</div>

```julia
julia> function foo()
       b=zeros(UInt16,1000000);
       for n=1:size(b,1)
          b[n]=mod(n,10)
       end
       end
foo (generic function with 1 method)

julia> @time foo()
  0.002235 seconds (2 allocations: 1.907 MiB)

```

Seems like you are right.

---

<div class="post-metadata">

### Author: ![RainerHeintzmann](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rainerheintzmann/32/19726_2.png) [@RainerHeintzmann](https://discourse.julialang.org/u/RainerHeintzmann)
#### Post date: [August 1, 2022, 2:06pm UTC](https://discourse.julialang.org/t/memory-on-array-element-assignment/85069/4 "2022-08-01T14:06:53Z")

</div>

So I tried to dig deeper and it turned out that a datatype argument is at the bottom of my problem:

```julia
julia> function foo(dtype = UInt32)
              b=zeros(dtype,350,20,1,128);
              for n = 1:length(b)
                 b[n] = one(dtype) 
              end
       end
foo (generic function with 2 methods)

julia> @time foo()
  0.085849 seconds (895.49 k allocations: 17.082 MiB, 7.75% gc time)

```

If you replace the `dtype` directly by `UInt32` the allocations are gone. I guess this should be handled via an proper explicit dispatch, but it is a bit odd that these allocations are appearing.

---

<div class="post-metadata">

### Author: ![PeterSimon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petersimon/32/25193_2.png) [@PeterSimon](https://discourse.julialang.org/u/PeterSimon)
#### Post date: [August 1, 2022, 4:22pm UTC](https://discourse.julialang.org/t/memory-on-array-element-assignment/85069/5 "2022-08-01T16:22:37Z")

</div>

At first I thought that `foo` was type-unstable, but since it always returns `nothing::Nothing`, I don’t think that satisfies the definition of type-instability. However, if you modify the function to accept a number of a specific type, then the allocation also goes away:

```julia
julia> function foo2(x = one(UInt32))
           dtype = typeof(x)
           b=zeros(dtype,350,20,1,128)
           for n = 1:length(b)
               b[n] = one(dtype)
           end
       end
foo2 (generic function with 2 methods)

julia> foo2(); @time foo2()
  0.000715 seconds (3 allocations: 3.418 MiB)

julia> foo2(1.0); @time foo2(1.0)
  0.001424 seconds (3 allocations: 6.836 MiB)

```

---

<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: [August 1, 2022, 4:53pm UTC](https://discourse.julialang.org/t/memory-on-array-element-assignment/85069/6 "2022-08-01T16:53:41Z")

</div>

The correct signature is

```julia
function foo(::Type{T}) where {T}

```

Otherwise, you will not get method specialization, and you’ll just get a generic method `foo(::DataType)`

---

<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: [August 1, 2022, 5:03pm UTC](https://discourse.julialang.org/t/memory-on-array-element-assignment/85069/7 "2022-08-01T17:03:55Z")

</div>

> [@RainerHeintzmann](#):
>
> ```julia
> function foo(dtype = UInt32)
> b=zeros(dtype,350,20,1,128);
> for n = 1:length(b)
> b[n] = one(dtype) 
> end
> end
> 
> ```

BTW, this function returns nothing, and has no effects that are observable from the outside. In principle, it can be simplified to

```julia
foo(dtype) = nothing

```

To be sure some work really happens, `return` the array.

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [August 1, 2022, 5:26pm UTC](https://discourse.julialang.org/t/memory-on-array-element-assignment/85069/8 "2022-08-01T17:26:39Z")

</div>

> [@PeterSimon](#):
>
> `function foo2(x = one(UInt32))`

> [@DNF](#):
>
> Otherwise, you will not get method specialization, and you’ll just get a generic method `foo(::DataType)`

[https://docs.julialang.org/en/v1/manual/performance-tips/#Be-aware-of-when-Julia-avoids-specializing](https://docs.julialang.org/en/v1/manual/performance-tips/#Be-aware-of-when-Julia-avoids-specializing)

> As a heuristic, Julia avoids automatically specializing on argument type parameters in three specific cases: `Type` , `Function` , and `Vararg` . Julia will always specialize when the argument is used within the method, but not if the argument is just passed through to another function. This usually has no performance impact at runtime and [improves compiler performance](https://docs.julialang.org/en/v1/devdocs/functions/#compiler-efficiency-issues). If you find it does have a performance impact at runtime in your case, you can trigger specialization by adding a type parameter to the method declaration.

---

<div class="post-metadata">

### Author: ![RainerHeintzmann](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rainerheintzmann/32/19726_2.png) [@RainerHeintzmann](https://discourse.julialang.org/u/RainerHeintzmann)
#### Post date: [August 3, 2022, 6:43am UTC](https://discourse.julialang.org/t/memory-on-array-element-assignment/85069/9 "2022-08-03T06:43:14Z")

</div>

You are right, but then it is all the more surprising that the function causes so many allocations. If you return `b`, you also obtain these allocations.

---

<div class="post-metadata">

### Author: ![RainerHeintzmann](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rainerheintzmann/32/19726_2.png) [@RainerHeintzmann](https://discourse.julialang.org/u/RainerHeintzmann)
#### Post date: [August 3, 2022, 6:45am UTC](https://discourse.julialang.org/t/memory-on-array-element-assignment/85069/10 "2022-08-03T06:45:21Z")

</div>

Interesting point. However it is still a bit unclear, why allocations result by just this simple assignment. Is this really unavoidable due to the resulting dynamic typing?

---

<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: [August 3, 2022, 6:53am UTC](https://discourse.julialang.org/t/memory-on-array-element-assignment/85069/11 "2022-08-03T06:53:40Z")

</div>

I didn’t mean to say that the compiler converts the program to do nothing, only that it _could, in principle_, do that in the not-so-distant future.

> [@RainerHeintzmann](#):
>
> However it is still a bit unclear, why allocations result by just this simple assignment.

Not sure I understand the question correctly, but I don’t think this has to do with assignment. The allocations occur when allocating and initializing the array, `b`, and when subsequently updating its elements.
