# Arithmetic overflow when trying to benchmark some digest

**URL:** <https://forum.crystal-lang.org/t/arithmetic-overflow-when-trying-to-benchmark-some-digest/2957>\
**Category:** Help & Support\
**Created:** [February 12, 2021, 4:57pm UTC](https://forum.crystal-lang.org/t/arithmetic-overflow-when-trying-to-benchmark-some-digest/2957 "2021-02-12T16:57:39Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![jwoertink](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jwoertink/32/50_2.png) [@jwoertink](https://forum.crystal-lang.org/u/jwoertink)\
**Post date:** [February 12, 2021, 4:57pm UTC](https://forum.crystal-lang.org/t/arithmetic-overflow-when-trying-to-benchmark-some-digest/2957/1 "2021-02-12T16:57:39Z")

</div>

I randomly came across this benchmark of some ruby code [ruby Digest::\* benchmark · GitHub](https://gist.github.com/morimori/1330095)  
and I got curious to see what that would look like in crystal.

Here’s my attempt at the same benchmark:

```crystal
require "digest"
require "benchmark"

SRC = File.read("/dev/urandom")[0, 4096]

Benchmark.bm do |bm|
  bm.report("MD5") { 100000.times { Digest::MD5.hexdigest(SRC) } }
  bm.report("SHA1") { 100000.times { Digest::SHA1.hexdigest(SRC) } }
  bm.report("SHA256") { 100000.times { Digest::SHA256.hexdigest(SRC) } }
end

```

but when I run this, I get an Arithmetic overflow error.

```nohighlight
Unhandled exception: Arithmetic overflow (OverflowError)
  from Math@Math::pw2ceil<Int32>:Int32
  from /usr/local/Cellar/crystal/0.36.1_2/src/string/builder.cr:124:5 in 'write'
  from /usr/local/Cellar/crystal/0.36.1_2/src/io.cr:1120:7 in '__crystal_main'
  from /usr/local/Cellar/crystal/0.36.1_2/src/crystal/main.cr:110:5 in 'main'

```

I didn’t want to just post a bug in case I was doing something weird in my code example.

```nohighlight
❯ crystal -v
Crystal 0.36.1 (2021-02-02)

LLVM: 11.0.1
Default target: x86_64-apple-macosx

```

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [February 12, 2021, 5:42pm UTC](https://forum.crystal-lang.org/t/arithmetic-overflow-when-trying-to-benchmark-some-digest/2957/2 "2021-02-12T17:42:27Z")

</div>

`File.read(/dev/urandom")` reads from `/dev/urandom` to the end. But there’s no end. You can always read more from `/dev/urandom`.

You might use something like this instead:

```auto
SRC = String.build do |io|
  File.open("/dev/urandom") do |file|
    IO.copy(file, io, 4096)
  end
end

```

Maybe we should add a `limit` parameter to `File.read`.

And the error message could be improved, i.e. rescue `OverflowError` and raise `IO::Error` instead in `String::Builder#write` (also in similar places).

---

<div class="post-metadata">

**Author:** ![jwoertink](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jwoertink/32/50_2.png) [@jwoertink](https://forum.crystal-lang.org/u/jwoertink)\
**Post date:** [February 12, 2021, 6:40pm UTC](https://forum.crystal-lang.org/t/arithmetic-overflow-when-trying-to-benchmark-some-digest/2957/3 "2021-02-12T18:40:04Z")

</div>

Ah. Ok thanks! That makes sense. Yeah, a `limit` option on `read` would be pretty cool. Want me to open an issue on that?

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [February 12, 2021, 11:40pm UTC](https://forum.crystal-lang.org/t/arithmetic-overflow-when-trying-to-benchmark-some-digest/2957/4 "2021-02-12T23:40:56Z")

</div>

You can do something like File.open(filename, &.gets(limit)), there’s no need to change anything.

---

<div class="post-metadata">

**Author:** ![jwoertink](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jwoertink/32/50_2.png) [@jwoertink](https://forum.crystal-lang.org/u/jwoertink)\
**Post date:** [February 13, 2021, 12:02am UTC](https://forum.crystal-lang.org/t/arithmetic-overflow-when-trying-to-benchmark-some-digest/2957/5 "2021-02-13T00:02:54Z")

</div>

Nice! That’s handy. Yeah, I’m all down for if there’s already a built-in way. I guess it’s just a matter of knowing how to do those things.

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [February 13, 2021, 12:08am UTC](https://forum.crystal-lang.org/t/arithmetic-overflow-when-trying-to-benchmark-some-digest/2957/6 "2021-02-13T00:08:22Z")

</div>

Although not directly related to this specific context (as the file is infinite), it is possible to pass a file path instead of the actual data. E.g.

```auto
Digest::SHA256.hexdigest &.file "./foo.txt"

```

Which can be handy for larger files.

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [February 13, 2021, 1:55am UTC](https://forum.crystal-lang.org/t/arithmetic-overflow-when-trying-to-benchmark-some-digest/2957/7 "2021-02-13T01:55:45Z")

</div>

`gets(limit)` stops at line break. So that’s not a generic alternative.
