# Allocation due to \`@noinline\` for unsafe\_read and unsafe\_write in io.jl

**URL:** <https://discourse.julialang.org/t/allocation-due-to-noinline-for-unsafe-read-and-unsafe-write-in-io-jl/69421>\
**Category:** Internals & Design\
**Tags:** question\
**Created:** [October 8, 2021, 8:02am UTC](https://discourse.julialang.org/t/allocation-due-to-noinline-for-unsafe-read-and-unsafe-write-in-io-jl/69421 "2021-10-08T08:02:02Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Paul\_Depping](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paul_depping/32/27997_2.png) [@Paul\_Depping](https://discourse.julialang.org/u/Paul_Depping)\
**Post date:** [October 8, 2021, 8:02am UTC](https://discourse.julialang.org/t/allocation-due-to-noinline-for-unsafe-read-and-unsafe-write-in-io-jl/69421/1 "2021-10-08T08:02:02Z")

</div>

I’m currently working with a lot of File IO, and I noticed that whenever i call the function `write(s::IO, x::Union{Int16,UInt16,Int32,UInt32,Int64,UInt64,Int128,UInt128,Float16,Float32,Float64})`, there is an Allocation.

```nohighlight
julia> using BenchmarkTools

julia> const io = open(tempname(; cleanup=true), "w")
IOStream(<file /tmp/jl_vp1BTP>)

julia> @btime write(io, 100)
  59.570 ns (1 allocation: 16 bytes)
8

```

After testing around with it and where this allocation happens, I’ve concluded that this is due to the function

```nohighlight
@noinline unsafe_write(s::IO, p::Ref{T}, n::Integer) where {T} =
    unsafe_write(s, unsafe_convert(Ref{T}, p)::Ptr, n) # mark noinline to ensure ref is gc-rooted somewhere (by the caller)

```

in io.jl, line 673-674. I’m wondering why the `@noinline` here is needed, and why `GC.@preserve p` would not be used instead. From my testing, overwriting that function, using `GC.@preserve p` leads to no allocations.

```julia
julia> function Base.unsafe_write(s::IO, p::Ref{T}, n::Integer) where T
           GC.@preserve p unsafe_write(s, Base.unsafe_convert(Ref{T}, p)::Ptr, n)
       end

julia> @btime write(io, 100)
  51.872 ns (0 allocations: 0 bytes)
8

```

Am I missing something here? Am I misunderstanding the role of GC-Rooting it via the caller instead of using `GC.@preserve`?

The same `@noinline` is present in

```julia
@noinline unsafe_read(s::IO, p::Ref{T}, n::Integer) where {T} = unsafe_read(s, unsafe_convert(Ref{T}, p)::Ptr, n) # mark noinline to ensure ref is gc-rooted somewhere (by the caller)

```

and generic IO types that go into this function when calling e.g. `read(io, Int)` (IOStream goes into a specialized function that doesn’t cause an allocation) have the same issue of having an allocation.

```julia
julia> struct tstio <: IO
           b::UInt8
       end

julia> Base.read(t::tstio, ::Type{UInt8}) = t.b

julia> Base.write(::tstio, x::UInt8) = 1

julia> const t = tstio(0xFF)
tstio(0xff)

julia> @btime read(t, UInt64)
  11.796 ns (1 allocation: 16 bytes)
0xffffffffffffffff

julia> function Base.unsafe_read(s::IO, p::Ref{T}, n::Integer) where {T}
           GC.@preserve p unsafe_read(s, Base.unsafe_convert(Ref{T}, p)::Ptr, n)
       end

julia> @btime read(t, UInt64)
  1.494 ns (0 allocations: 0 bytes)
0xffffffffffffffff

```

Is the `@noinline` in these functions, which seems to have last been edited 4/5 years ago according to the git blame still needed, or does switching it out with `GC.@preserve` make more sense?

---

<div class="post-metadata">

**Author:** ![Paul\_Depping](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paul_depping/32/27997_2.png) [@Paul\_Depping](https://discourse.julialang.org/u/Paul_Depping)\
**Post date:** [October 8, 2021, 8:27am UTC](https://discourse.julialang.org/t/allocation-due-to-noinline-for-unsafe-read-and-unsafe-write-in-io-jl/69421/2 "2021-10-08T08:27:29Z")

</div>

I have found that this has previously been discussed over on the github, and since I barely know anything about Julias Task switching yet my understanding of that ends here. [https://github.com/JuliaLang/julia/pull/39759](https://github.com/JuliaLang/julia/pull/39759)
