# Abysmal performance when reading block of data from disk with Julia

**URL:** <https://discourse.julialang.org/t/abysmal-performance-when-reading-block-of-data-from-disk-with-julia/124988>\
**Category:** Performance\
**Created:** [January 20, 2025, 8:39pm UTC](https://discourse.julialang.org/t/abysmal-performance-when-reading-block-of-data-from-disk-with-julia/124988 "2025-01-20T20:39:56Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![world-peace](https://avatars.discourse-cdn.com/v4/letter/w/9f8e36/32.png) [@world-peace](https://discourse.julialang.org/u/world-peace)\
**Post date:** [January 20, 2025, 8:39pm UTC](https://discourse.julialang.org/t/abysmal-performance-when-reading-block-of-data-from-disk-with-julia/124988/1 "2025-01-20T20:39:56Z")

</div>

See the code below.

```julia
const count = 10000

function create()
    v = rand(Int64, count)
    open("data.bin", "w") do ofile
        write(ofile, v)
    end
end

function test()
    open("data.bin") do ifile
        v = Vector{Int64}(undef, len)
        v = read!(ifile, v)
        return v
    end
end

```

This is a very simple, arguably trivial, thing to want to do. Other languages cope perfectly fine with this. For example, the runtime performance of the same code written in C++ is over 10,000 times faster.

- C++ runtime: few nanoseconds
- Julia runtime: nearly a whole millisecond

I can’t believe how bad it is. It’s a joke. It’s a totally trivial operation.

1. Read block of data using OS call
2. Perform O(1) reinterpret of returned data so that the runtime treats it as a `Vector{Int64}` instead of `Vector{UInt8}`. There is _ **no need** _ for this to do any type-safety or runtime type-checking nonsense.

Since the OS is doing most of the work here, there is no excuse for this.

---

<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:** [January 20, 2025, 8:48pm UTC](https://discourse.julialang.org/t/abysmal-performance-when-reading-block-of-data-from-disk-with-julia/124988/2 "2025-01-20T20:48:24Z")

</div>

This code doesn’t run as written. Assuming you meant to write,

```julia
function test()
    open("data.bin") do ifile
    v = Vector{Int64}(undef, div(count,8))
        v = read!(ifile, v)
        return v
    end
end

```

I’m seeing a time of 7.2 microseconds. Do you have the C++ code to show the few nanosecond timing? I’m surprised by this given that NVME drives have a few microsends latency.

---

<div class="post-metadata">

**Author:** ![world-peace](https://avatars.discourse-cdn.com/v4/letter/w/9f8e36/32.png) [@world-peace](https://discourse.julialang.org/u/world-peace)\
**Post date:** [January 20, 2025, 8:55pm UTC](https://discourse.julialang.org/t/abysmal-performance-when-reading-block-of-data-from-disk-with-julia/124988/3 "2025-01-20T20:55:20Z")

</div>

Turn your GC on

---

<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:** [January 20, 2025, 9:04pm UTC](https://discourse.julialang.org/t/abysmal-performance-when-reading-block-of-data-from-disk-with-julia/124988/4 "2025-01-20T21:04:12Z")

</div>

GC is on. This doesn’t allocate anywhere near enough for the GC to run every time.

```julia
julia> @benchmark test()
BenchmarkTools.Trial: 10000 samples with 4 evaluations per sample.
 Range (min … max): 6.963 μs … 2.388 ms ┊ GC (min … max): 0.00% … 91.97%
 Time (median): 7.928 μs ┊ GC (median): 0.00%
 Time (mean ± σ): 9.896 μs ± 35.216 μs ┊ GC (mean ± σ): 8.37% ± 2.67%

     ▅██▆▄▃▃▃▃▃▃▂▂▂▂▂▂▁▁▁ ▁▂▂▁▁▁ ▁▁▁ ▁ ▂
  ▅▄▆█████████████████████████████████████████▆█▆▇▇▆▇▇▇▅▆▄▅▅ █
  6.96 μs Histogram: log(frequency) by time 16.9 μs <

 Memory estimate: 10.57 KiB, allocs estimate: 16.

```

---

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [January 20, 2025, 9:06pm UTC](https://discourse.julialang.org/t/abysmal-performance-when-reading-block-of-data-from-disk-with-julia/124988/5 "2025-01-20T21:06:15Z")

</div>

> [@world-peace](#):
>
> C++ runtime: few nanoseconds

I strongly suspect that the your C++ compiler optimized away all of your I/O code.

---

<div class="post-metadata">

**Author:** ![world-peace](https://avatars.discourse-cdn.com/v4/letter/w/9f8e36/32.png) [@world-peace](https://discourse.julialang.org/u/world-peace)\
**Post date:** [January 20, 2025, 9:27pm UTC](https://discourse.julialang.org/t/abysmal-performance-when-reading-block-of-data-from-disk-with-julia/124988/6 "2025-01-20T21:27:06Z")

</div>

This post was temporarily hidden by the community for possibly being off-topic, unfocused, inappropriate, or spammy.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [January 20, 2025, 9:35pm UTC](https://discourse.julialang.org/t/abysmal-performance-when-reading-block-of-data-from-disk-with-julia/124988/7 "2025-01-20T21:35:16Z")

</div>

> [@world-peace](#):
>
> I am providing free work here.

You’re the one asking for assistance in the first place, not being paid for that is expected everywhere. We all participate for free and try to get along here. As for the work itself, you’re not doing enough for reproducibility or profiling. Provide all the code, including the benchmarking.

---

<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:** [January 20, 2025, 9:36pm UTC](https://discourse.julialang.org/t/abysmal-performance-when-reading-block-of-data-from-disk-with-julia/124988/8 "2025-01-20T21:36:02Z")

</div>

Can you post the C++ code that you’re benchmarking against? I’m really interested to see how C++ is doing this in nanoseconds.

---

<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:** [January 20, 2025, 10:01pm UTC](https://discourse.julialang.org/t/abysmal-performance-when-reading-block-of-data-from-disk-with-julia/124988/9 "2025-01-20T22:01:48Z")

</div>

> [@world-peace](#):
>
> C++ runtime: few nanoseconds

10,000 64-bit integers read in a few nanoseconds. Depending on what ‘a few nanoseconds’ means, that’s fast.

- If it means 1000 nanoseconds, it is 80GB/sec
- If it means 100 nanoseconds, it is 800GB/sec
- If it means 10 nanoseconds, it is 8TB/sec

My own SSD can maybe do a few GB/sec at most.

---

<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:** [January 20, 2025, 10:16pm UTC](https://discourse.julialang.org/t/abysmal-performance-when-reading-block-of-data-from-disk-with-julia/124988/10 "2025-01-20T22:16:27Z")

</div>

Running this code:

```julia
function readtest!(v, filename)
    open(filename, "r") do fid
        read!(fid, v)
    end
    return v
end

```

with a pre-allocated `v`, I get a runtime of 43us, which translates to 1.7GB/sec, reasonably close to what I belive to be my disk read speed.

Note that caching is likely to play some role here, not sure how to benchmark this in a bulletproof way, but something like that appears to be a problem in your C++ code as well, I would guess.

---

<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:** [January 20, 2025, 10:24pm UTC](https://discourse.julialang.org/t/abysmal-performance-when-reading-block-of-data-from-disk-with-julia/124988/11 "2025-01-20T22:24:33Z")

</div>

Specifically, dual channel DDR5 ram is only ~100GB/s so it’s somewhat unbelievable to me that this could be finishing in less than ~800 microseconds.

---

<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:** [January 20, 2025, 10:26pm UTC](https://discourse.julialang.org/t/abysmal-performance-when-reading-block-of-data-from-disk-with-julia/124988/12 "2025-01-20T22:26:49Z")

</div>

> [@Oscar\_Smith](#):
>
> ~800 microseconds.

nanoseconds?

---

<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:** [January 20, 2025, 10:31pm UTC](https://discourse.julialang.org/t/abysmal-performance-when-reading-block-of-data-from-disk-with-julia/124988/13 "2025-01-20T22:31:26Z")

</div>

yes.

---

<div class="post-metadata">

**Author:** ![simsurace](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simsurace/32/30216_2.png) [@simsurace](https://discourse.julialang.org/u/simsurace)\
**Post date:** [January 21, 2025, 8:08am UTC](https://discourse.julialang.org/t/abysmal-performance-when-reading-block-of-data-from-disk-with-julia/124988/14 "2025-01-21T08:08:24Z")

</div>

> I strongly suspect that the your C++ compiler optimized away all of your I/O code.

Thinking about this for a bit, wouldn’t this be a very bold move and circular reasoning on the part of the compiler (even if the program removes the file afterwards)?

In any case, I think seeing the C++ program that is being compiled and benchmarked would shed some light onto what’s going on.

---

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [January 21, 2025, 2:00pm UTC](https://discourse.julialang.org/t/abysmal-performance-when-reading-block-of-data-from-disk-with-julia/124988/15 "2025-01-21T14:00:41Z")

</div>

> [@simsurace](#):
>
> wouldn’t this be a very bold move and circular reasoning on the part of the compiler (even if the program removes the file afterwards)?

I don’t quite follow. My comment was also a bit short and imprecise. Trying to be a bit more precise: I think if the compiler realizes that the result of the reading operation is completely unused it might just optimize the actual read away. Opening the file might remain (because it could throw) and that could explain why the call still takes “a few nanoseconds”.

But as you say: Without knowing the code that was actually timed, it is impossible to say what is going on.

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [January 21, 2025, 4:13pm UTC](https://discourse.julialang.org/t/abysmal-performance-when-reading-block-of-data-from-disk-with-julia/124988/16 "2025-01-21T16:13:49Z")

</div>

Something that can go in nanoseconds is simply mmapping the file, esp because it’s O(1); like “reading” a gigabyte file in mere microseconds.

Is this mayhaps what you’re comparing to @world-peace ?

You can use mmap the same way in julia.

What you would need to look at for that is both C/C++ code and strace or similar output.

However, while mapping is often an appropriate alternative to reading a file, it’s very inappropriate to conflate both in benchmarks – if you e.g. modify the array, copy-on-write-on-pagefault is likely to be slower than actually reading the data in the first place.
