# Overflow behaviour - how to explain

**URL:** <https://discourse.julialang.org/t/overflow-behaviour-how-to-explain/996>\
**Category:** General Usage\
**Tags:** question, integer-overflow\
**Created:** [December 16, 2016, 6:02pm UTC](https://discourse.julialang.org/t/overflow-behaviour-how-to-explain/996 "2016-12-16T18:02:09Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Balinus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/balinus/32/243_2.png) [@Balinus](https://discourse.julialang.org/u/Balinus)\
**Post date:** [December 16, 2016, 6:02pm UTC](https://discourse.julialang.org/t/overflow-behaviour-how-to-explain/996/1 "2016-12-16T18:02:09Z")

</div>

Hello,

I’m preparing a little introductory presentation for my team on Julia. I’d like to do some slides on where people should be careful. Overflow bahaviour is certainly one of them imho. I just don’t know how to explain why there is this possibility of overflow. Is it just because if there were automatic promotion to bigint and bigfloat, the code would be slower? How much slower by the way? Just so I can give an order of magnitude.

Thanks for any explanation! I’m not in CS, nor are my team 🙂

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [December 16, 2016, 6:28pm UTC](https://discourse.julialang.org/t/overflow-behaviour-how-to-explain/996/2 "2016-12-16T18:28:25Z")

</div>

> How much slower by the way?

You should check sth like pypy for a JIT that optimize it to extreme and it’s hard to tell how much overhead it adds.

Julia is designed so that it doesn’t have to rely on any of those less reliable optimizations so it has a really simple compiler. With that the overhead will be \>1000x.

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [December 16, 2016, 6:50pm UTC](https://discourse.julialang.org/t/overflow-behaviour-how-to-explain/996/3 "2016-12-16T18:50:42Z")

</div>

Testing it:

```julia
immutable MyInt{T<:Integer}
    a::T
end
Base.:+(i::MyInt{Int}, ii::Int) =  
    i.a>typemax(Int)-ii ? MyInt(BigInt(i.a)+ii) : MyInt(i.a+ii)
Base.:+(i::MyInt{BigInt}, ii::Int) = MyInt(i.a+ii)

function addone(out, n)
    for nn=1:n
        out += 1
    end
    out
end

using BenchmarkTools
@show @benchmark addone(1, 10^4)
@show @benchmark addone(MyInt(1), 10^4)
@show @benchmark addone(MyInt(BigInt(1)), 10^4)
nothing

```

gives:

```julia
@benchmark(addone(1,10 ^ 4)) = BenchmarkTools.Trial:
  memory estimate: 0.00 bytes
  allocs estimate: 0
  --------------
  minimum time: 7.686 ns (0.00% GC)
...

@benchmark(addone(MyInt(1),10 ^ 4)) = BenchmarkTools.Trial:
  memory estimate: 156.27 kb
  allocs estimate: 10001
  --------------
  minimum time: 127.549 μs (0.00% GC)
...

@benchmark(addone(MyInt(BigInt(1)),10 ^ 4)) = BenchmarkTools.Trial:
  memory estimate: 781.32 kb
  allocs estimate: 40003
  --------------
  minimum time: 1.088 ms (0.00% GC)
 ...

```

So about 20,000x slower. One of the big performance killers is that the function is not type-stable.

---

<div class="post-metadata">

**Author:** ![Balinus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/balinus/32/243_2.png) [@Balinus](https://discourse.julialang.org/u/Balinus)\
**Post date:** [December 16, 2016, 7:11pm UTC](https://discourse.julialang.org/t/overflow-behaviour-how-to-explain/996/4 "2016-12-16T19:11:05Z")

</div>

Nice for this benchmarking. The hit is really heavy. So, it’s mostly a matter that the functions become not type-stable?

---

<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:** [December 16, 2016, 7:41pm UTC](https://discourse.julialang.org/t/overflow-behaviour-how-to-explain/996/5 "2016-12-16T19:41:19Z")

</div>

Could this be what you’re looking for?

[http://ucidatascienceinitiative.github.io/IntroToJulia/Html/WhyJulia](http://ucidatascienceinitiative.github.io/IntroToJulia/Html/WhyJulia)

The example I use isn’t overflow and instead it’s `2^(-5)`, but yes it’s type-stability that’s the reason for this “lack of safety” (but for good reasons!).

Note that page is part of a larger series:

[http://ucidatascienceinitiative.github.io/IntroToJulia/](http://ucidatascienceinitiative.github.io/IntroToJulia/)

> [@Balinus](#):
>
> I’d like to do some slides on where people should be careful.

Maybe this resource could be helpful here?

> **[7 Julia Gotchas and How to Handle Them - Stochastic Lifestyle](http://www.stochasticlifestyle.com/7-julia-gotchas-handle/)**
>
> Let me start by saying Julia is a great language. I love the language, it is what I find to be the most powerful and intuitive language that I have ever used. It’s undoubtedly my favorite language. That said, there are some “gotchas”, tricky little...

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [December 16, 2016, 7:43pm UTC](https://discourse.julialang.org/t/overflow-behaviour-how-to-explain/996/6 "2016-12-16T19:43:21Z")

</div>

Changing to  
`Base.:+(i::MyInt{Int}, ii::Int) = i.a>typemax(Int)-ii ? MyInt((i.a)+ii+2) : MyInt(i.a+ii)`  
makes it type-stable and results in 5micro. So, most of the slow-down is from the conditional. Note however, that using a type-unstable function “poisons” the code which uses it and makes it slow.

---

<div class="post-metadata">

**Author:** ![Balinus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/balinus/32/243_2.png) [@Balinus](https://discourse.julialang.org/u/Balinus)\
**Post date:** [December 16, 2016, 7:53pm UTC](https://discourse.julialang.org/t/overflow-behaviour-how-to-explain/996/7 "2016-12-16T19:53:30Z")

</div>

Thanks for the links, this will certainly fuel some of my slides 🙂 Especially the “WhyJulia”, it explains very well where newcomers needs to look for safety.

> [@mauro3](#):
>
> Changing toBase.:+(i::MyInt{Int}, ii::Int) = i.a\>typemax(Int)-ii ? MyInt((i.a)+ii+2) : MyInt(i.a+ii) makes it type-stable and results in 5micro. So, most of the slow-down is from the conditional. Note however, that using a type-unstable function “poisons” the code which uses it and makes it slow.

Noted!

---

<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:** [December 19, 2016, 11:55am UTC](https://discourse.julialang.org/t/overflow-behaviour-how-to-explain/996/8 "2016-12-19T11:55:45Z")

</div>

It should be noted that there are many fancy tricks you can do to make BigInts faster and even combine the basic integer type with the BigInt type, but it inevitably adds complications and removes transparency – and makes it much harder to reason about the performance of one’s code. It also tends to make the representation of system integers incompatible with how C/Fortran represents them. So it all depends on your priorities. We should, however, have faster BigInts that are stored inline when possible.

---

<div class="post-metadata">

**Author:** ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)\
**Post date:** [December 21, 2016, 5:00pm UTC](https://discourse.julialang.org/t/overflow-behaviour-how-to-explain/996/9 "2016-12-21T17:00:20Z")

</div>

> [@mauro3](#):
>
> makes it type-stable and results in 5micro.

This is also far from the whole story. You’re most often not just adding in a loop. If you do some other work inbetween that is memory (not cache) bound, then it will not matter much; and latency of branch will be hidden by other (memory) latencies.

[With unrolling of loops, a clever optimizer could also optimize away some checks.]

[If SIMD integer use was common (I guess not…) I aslo assume you could check many overflows at once…]

I would like overflow traps to get added as an option to Julia later (command line switch). The type here would be a first step, so not critical to have the switch. I’m not sure if I could swap out the current integer type for my type given the same source code…

I tried (probably what you want or might often be enough):

```julia
julia> Base.:+(i::MyInt{Int}, ii::Int) =
         i.a>typemax(Int)-ii ? throw("Overflow") : MyInt(i.a+ii)

```

```julia
@benchmark(addone(1,10 ^ 4)) = BenchmarkTools.Trial: 
  memory estimate: 0.00 bytes
  allocs estimate: 0
  minimum time: 7.00 ns (0.00% GC)
...

@benchmark(addone(MyInt(1),10 ^ 4)) = BenchmarkTools.Trial: 
  memory estimate: 0.00 bytes
  allocs estimate: 0
  minimum time: 2.65 μs (0.00% GC)

```

[Before on my machine

```julia
@benchmark(addone(MyInt(1),10 ^ 4)) = BenchmarkTools.Trial: 
  memory estimate: 156.27 kb
  minimum time: 106.41 μs (0.00% GC)

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [December 21, 2016, 6:15pm UTC](https://discourse.julialang.org/t/overflow-behaviour-how-to-explain/996/10 "2016-12-21T18:15:13Z")

</div>

In practice, with 64-bit integers, overflow is not a serious concern in my experience.

If you are counting actual things (bytes, loop iterations) etcetera, `Int64` will not overflow. If you are doing number theory, then you need BigInt. In real applications, you know which of those two circumstances you are in. (I think Stefan made this point somewhere a long time ago?)

(On 16- and even 32-bit machines, of course, matters were much different.)

(`BigFloat` is a totally different story; it’s not practical to automatically promote to `BigFloat` regardless of the language or performance, because that requires automation of floating-point error analysis, which seems to be almost impossible in practice [inflated claims about “unums” notwithstanding].)
