# (Compiler) Performance of Dict

**URL:** https://discourse.julialang.org/t/compiler-performance-of-dict/27986
**Category:** General Usage
**Created:** [August 26, 2019, 6:32am UTC](https://discourse.julialang.org/t/compiler-performance-of-dict/27986 "2019-08-26T06:32:49Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![tobias.knopp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tobias.knopp/32/7551_2.png) [@tobias.knopp](https://discourse.julialang.org/u/tobias.knopp)
#### Post date: [August 26, 2019, 6:32am UTC](https://discourse.julialang.org/t/compiler-performance-of-dict/27986/1 "2019-08-26T06:32:49Z")

</div>

In [Roadmap for a faster time-to-first-plot?](https://discourse.julialang.org/t/roadmap-for-a-faster-time-to-first-plot/22956), it was suggested by @ChrisRackauckas to circumvent the usage of Dicts since they slow down compile time performance. I would love to get suggestions how to actually do this.

In my application I am using TOML files for configuration and when reading TOML files, what I get back is a Dict. Any suggestions how to make the compiler faster in these situations? Does it make sense to convert the Dict into a struct for further processing?

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [August 26, 2019, 6:53am UTC](https://discourse.julialang.org/t/compiler-performance-of-dict/27986/2 "2019-08-26T06:53:06Z")

</div>

> [@tobias.knopp](#):
>
> what I get back is a Dict. Any suggestions how to make the compiler faster in these situations?

Does the type of these `Dict`s depend on the data, or is it always the same? In the latter case you should be fine.

---

<div class="post-metadata">

### Author: ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)
#### Post date: [August 26, 2019, 7:22am UTC](https://discourse.julialang.org/t/compiler-performance-of-dict/27986/3 "2019-08-26T07:22:31Z")

</div>

> [@tobias.knopp](#):
>
> Does it make sense to convert the Dict into a struct for further processing?

`Dict`s are structs:

> <https://github.com/JuliaLang/julia/blob/5e75cfe24ac65400b8faa2972c0ac8f8b1faa9dd/base/dict.jl#L78-L86>

Deeply nested parametric structs can be hard on the compiler, e.q. `Dict{A, Dict{B, Dict{C, Dict{D, E}}}} where {A, B, C, D, E}` but that’s not unique to `Dict`s.

---

<div class="post-metadata">

### Author: ![tobias.knopp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tobias.knopp/32/7551_2.png) [@tobias.knopp](https://discourse.julialang.org/u/tobias.knopp)
#### Post date: [August 26, 2019, 7:32am UTC](https://discourse.julialang.org/t/compiler-performance-of-dict/27986/4 "2019-08-26T07:32:56Z")

</div>

> [@kristoffer.carlsson](#):
>
> Deeply nested parametric structs can be hard on the compiler, e.q. `Dict{A, Dict{B, Dict{C, Dict{D, E}}}} where {A, B, C, D, E}` but that’s not unique to `Dict` s.

Yes, but that’s the architecture of TOML.jl. It returns nested Dicts.

Again, my question is, whether anybody has some performance tips how to circumvent the long inference times. When I remember correctly Pkg had the same issue and solved it by compiling those things into the system image.

---

<div class="post-metadata">

### Author: ![tobias.knopp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tobias.knopp/32/7551_2.png) [@tobias.knopp](https://discourse.julialang.org/u/tobias.knopp)
#### Post date: [August 26, 2019, 7:34am UTC](https://discourse.julialang.org/t/compiler-performance-of-dict/27986/5 "2019-08-26T07:34:43Z")

</div>

> [@Tamas\_Papp](#):
>
> Does the type of these `Dict` s depend on the data, or is it always the same? In the latter case you should be fine.

I kind of know the structure of the TOML file. But I don’t want to write my own TOML parser. Therefore the question if it is possible using TOML.jl (which returns Dicts) and then converting that to a struct. Does that help or not?

---

<div class="post-metadata">

### Author: ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)
#### Post date: [August 26, 2019, 7:42am UTC](https://discourse.julialang.org/t/compiler-performance-of-dict/27986/6 "2019-08-26T07:42:21Z")

</div>

> [@tobias.knopp](#):
>
> Yes, but that’s the architecture of TOML.jl. It returns nested Dicts.

Yes, but the types are not nested. There is nothing inherently slow with Dicts. But code like

> <https://github.com/JuliaLang/Pkg.jl/blob/cf7fc6fe35d6bfb848597614dbbafd8289320efc/src/GraphType.jl#L125-L126>

might be slow to compile (not because of dicts but because of the nesting of types).

---

<div class="post-metadata">

### Author: ![tobias.knopp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tobias.knopp/32/7551_2.png) [@tobias.knopp](https://discourse.julialang.org/u/tobias.knopp)
#### Post date: [August 26, 2019, 7:46am UTC](https://discourse.julialang.org/t/compiler-performance-of-dict/27986/7 "2019-08-26T07:46:40Z")

</div>

That is true. The type is `Dict{AbstractString, Any}` and it then contains more Dicts of the same type. Not sure, why it is `AbstractString` and not `String`.

---

<div class="post-metadata">

### Author: ![tobias.knopp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tobias.knopp/32/7551_2.png) [@tobias.knopp](https://discourse.julialang.org/u/tobias.knopp)
#### Post date: [August 26, 2019, 7:50am UTC](https://discourse.julialang.org/t/compiler-performance-of-dict/27986/8 "2019-08-26T07:50:05Z")

</div>

for reference, I get

```julia
julia> @time a = TOML.parsefile("myfile.toml")
  1.242109 seconds (2.40 M allocations: 120.457 MiB, 11.85% gc time)
Dict{AbstractString,Any} with 6 entries:
  
julia> @time a = TOML.parsefile("myfile.toml")
  0.001002 seconds (2.15 k allocations: 97.641 KiB)
Dict{AbstractString,Any} with 6 entries:

```

The file has 2613 Bytes. Not sure for what it is allocating 120 MB.

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [August 26, 2019, 7:53am UTC](https://discourse.julialang.org/t/compiler-performance-of-dict/27986/9 "2019-08-26T07:53:54Z")

</div>

I wonder what would happen if we just added a bunch of Dict{Any,Any} or Dict{Symbol,Any} stuff to the sysimage and told people to prefer that (Any,Any should already have some coverage, but I wonder what would happen if we purposely made it pretty complete)

---

<div class="post-metadata">

### Author: ![tobias.knopp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tobias.knopp/32/7551_2.png) [@tobias.knopp](https://discourse.julialang.org/u/tobias.knopp)
#### Post date: [August 26, 2019, 8:09am UTC](https://discourse.julialang.org/t/compiler-performance-of-dict/27986/10 "2019-08-26T08:09:14Z")

</div>

Lets switch to a concrete example. Here are the numbers I get from Winston:

```julia
julia> @time using Winston
  2.744007 seconds (2.26 M allocations: 119.856 MiB, 2.29% gc time)

julia> @time plot(1:100)
  2.838665 seconds (7.31 M allocations: 376.682 MiB, 4.47% gc time)

```

The last time is not really complete since the window starts rendering after about 7 seconds. In its core, Winston uses a Dict for configuration

```julia
https://github.com/JuliaGraphics/Winston.jl/blob/master/src/Winston.jl#L113

```

My hyothesis, that is not proven but your post seems to indicate that it might be true, is that the performance issues are due to the usage of Dicts. Maybe we could learn from that example, how either

- Dicts can be accelerated, or
- How such code can be refactored to run fast.

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [August 26, 2019, 8:16am UTC](https://discourse.julialang.org/t/compiler-performance-of-dict/27986/11 "2019-08-26T08:16:40Z")

</div>

Try compiling just the dict portions to the sysimage and see what happens.

---

<div class="post-metadata">

### Author: ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)
#### Post date: [August 26, 2019, 8:40am UTC](https://discourse.julialang.org/t/compiler-performance-of-dict/27986/12 "2019-08-26T08:40:03Z")

</div>

If memory serves, the top three inference times for Revise’s startup are all `setindex!` functions for different Dict types, which is why I chose that for the example in [https://github.com/JuliaLang/julia/pull/31466](https://github.com/JuliaLang/julia/pull/31466).

And I agree with @ChrisRackauckas that certain programming patterns are unnecessarily hard on the compiler. Changing a `Dict{AbstractFloat,AbstractString}` to a `Dict{Any,Any}` is probably quite reasonable.

But in other ways, I think this is precisely the wrong time to be distorting your programming style in ways you might later regret to achieve faster startup. While faster compile/interpret performance will in aggregate be a really big job (indeed, its own research problem), areas like getting `setindex!` to precompile properly seem completely doable. My latest attempt to improve precompilation is [Change precompilation format to be more amenable to copying by timholy · Pull Request #32705 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/32705), which (as you’ll see from my comment) may not be in exactly the right direction but is attempting to address one of the bigger limitations. I’d guess that Jeff & Jameson haven’t yet been able to switch to making compile time their main priority, but once they do I suspect we’ll see a few gains fairly quickly (and the particular issue in 32705 seems quite “ripe” to me), and others will unfold over much longer time scales.

---

<div class="post-metadata">

### Author: ![tobias.knopp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tobias.knopp/32/7551_2.png) [@tobias.knopp](https://discourse.julialang.org/u/tobias.knopp)
#### Post date: [August 26, 2019, 9:02am UTC](https://discourse.julialang.org/t/compiler-performance-of-dict/27986/13 "2019-08-26T09:02:49Z")

</div>

I want to believe Tim, but since compile time is a non-trivial problem, I have some doubts that there will be a solution soon. This is really not meant as a critique and I want that you prove me wrong. My hope would be that 1.4 (which I expect in summer 2020) contains improvements.

---

<div class="post-metadata">

### Author: ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)
#### Post date: [August 26, 2019, 9:05am UTC](https://discourse.julialang.org/t/compiler-performance-of-dict/27986/14 "2019-08-26T09:05:40Z")

</div>

Yes, hoping for improvements in 1.4 (and further improvements in later releases) seems reasonable. But at least for your own personal use, I’d guess if you compile Julia yourself from `master` you might see some major benefits earlier than summer 2020.

---

<div class="post-metadata">

### Author: ![TsurHerman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tsurherman/32/1234_2.png) [@TsurHerman](https://discourse.julialang.org/u/TsurHerman)
#### Post date: [August 27, 2019, 10:01am UTC](https://discourse.julialang.org/t/compiler-performance-of-dict/27986/15 "2019-08-27T10:01:18Z")

</div>

Check out

[![](https://global.discourse-cdn.com/julialang/original/3X/b/5/b5a72c6ad5650e5fe5c5f8f5ce6d02af4f0c02ec.jpeg "2018 LLVM Developers’ Meeting: L. Hames & B. Loggins “Updating ORC JIT for Concurrency”") ](https://www.youtube.com/watch?v=MOQG5vkh9J8)

It seems that the road is already paved with the new ORC jit.  
You get concurrent compilation, object cache jit-dylib, the ability to delete compiled functions.

The only problem is the global method table a.k.a global multiple dispatch, which makes it very hard to cache compilation. Because as I pointed out in the past it is hard to prove that adding a module will not alter previously compiled code.

---

<div class="post-metadata">

### Author: ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)
#### Post date: [August 27, 2019, 11:19am UTC](https://discourse.julialang.org/t/compiler-performance-of-dict/27986/16 "2019-08-27T11:19:49Z")

</div>

> Because as I pointed out in the past it is hard to prove that adding a module will not alter previously compiled code.

That’s what our backedges are for. It will always be possible to load one tiny thing and force recompilation of a huge amount of code. For example, loading a module that does this:

```julia
import Base: +
+(x::Int, y::Int) = 0 # surprise!

```

will invalidate any method that adds `Int`s, so future calls will have to compile everything they need from scratch. The bigger problem is indeed tricky, but questions like “can we at least cache more of the results of inference? will it help in some circumstances?” are certainly going to have affirmative answers.

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [August 27, 2019, 11:46am UTC](https://discourse.julialang.org/t/compiler-performance-of-dict/27986/17 "2019-08-27T11:46:44Z")

</div>

Can Julia use the JIT concurrency and speculative JITing? That seems like it would solve a lot of the issues.

---

<div class="post-metadata">

### Author: ![lobingera](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lobingera/32/211_2.png) [@lobingera](https://discourse.julialang.org/u/lobingera)
#### Post date: [August 27, 2019, 12:13pm UTC](https://discourse.julialang.org/t/compiler-performance-of-dict/27986/18 "2019-08-27T12:13:24Z")

</div>

OT: Wasn’t actions like this - overwriting methods in other modules - the classical counterargument to method merging cross modules? I wasn’t aware that this is possible for Base, i always had the impression you can _extend_ Base.

---

<div class="post-metadata">

### Author: ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)
#### Post date: [August 27, 2019, 12:20pm UTC](https://discourse.julialang.org/t/compiler-performance-of-dict/27986/19 "2019-08-27T12:20:07Z")

</div>

> That’s what our backedges are for. It will always be possible to load one tiny thing and force recompilation of a huge amount of code.

If type piracy is disallowed, can one still cause invalidations? Would it be enough to forbid type piracy to be able to cache compiled code?

---

<div class="post-metadata">

### Author: ![KestutisMa](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kestutisma/32/7835_2.png) [@KestutisMa](https://discourse.julialang.org/u/KestutisMa)
#### Post date: [August 27, 2019, 3:57pm UTC](https://discourse.julialang.org/t/compiler-performance-of-dict/27986/20 "2019-08-27T15:57:28Z")

</div>

Looks like there were efforts to do “Speculative compilation support in LLVM ORC JIT Infrastructure” for Julia as Google Summer of Code 2019 project: [New LLVM JIT Features - #5 by jpsamaroo](https://discourse.julialang.org/t/new-llvm-jit-features/22754/5)

[Next page](https://discourse.julialang.org/t/compiler-performance-of-dict/27986.md?page=2)
