# Is it suggested to write functions for ::IO?

**URL:** <https://discourse.julialang.org/t/is-it-suggested-to-write-functions-for-io/79718>\
**Category:** Performance\
**Tags:** question\
**Created:** [April 20, 2022, 1:59am UTC](https://discourse.julialang.org/t/is-it-suggested-to-write-functions-for-io/79718 "2022-04-20T01:59:57Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Rratic](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rratic/32/24917_2.png) [@Rratic](https://discourse.julialang.org/u/Rratic)\
**Post date:** [April 20, 2022, 1:59am UTC](https://discourse.julialang.org/t/is-it-suggested-to-write-functions-for-io/79718/1 "2022-04-20T01:59:57Z")

</div>

I found that some of the functions in `Base` are written like `(::IO,::Any)`, and then uses `sprint` to wrap it so that it can return a string.  
For the following code:

```nohighlight
function A(io::IO)
print(io,"foo")
end
A()=sprint(A)
B()="foo"
B(io::IO)=print(io,B())

```

Which is quicker, A or B (maybe in more complicated cases than a single “foo”), and why?  
If one of them is quicker, does the conclusion also work for inputting(using IOBuffer to wrap a string)?

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [April 20, 2022, 5:59am UTC](https://discourse.julialang.org/t/is-it-suggested-to-write-functions-for-io/79718/2 "2022-04-20T05:59:55Z")

</div>

It’s usually written that way to save allocations. Strings in julia are immutable, so if you don’t actually need a string and just want to `write` some result somewhere (possibly on disk, to a socket, …), you can just pass the `IO` around instead. As such, “which is quicker” depends on your context, e.g. if you really do need a `String` you’re not really going to get around creating it.

---

<div class="post-metadata">

**Author:** ![Rratic](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rratic/32/24917_2.png) [@Rratic](https://discourse.julialang.org/u/Rratic)\
**Post date:** [April 20, 2022, 7:08am UTC](https://discourse.julialang.org/t/is-it-suggested-to-write-functions-for-io/79718/3 "2022-04-20T07:08:48Z")

</div>

I see, but I need the exact answer to “which is quicker” partly because I will use it for both cases(somtimes I need String and sometimes `IO`).

---

<div class="post-metadata">

**Author:** ![albheim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/albheim/32/34660_2.png) [@albheim](https://discourse.julialang.org/u/albheim)\
**Post date:** [April 20, 2022, 7:33am UTC](https://discourse.julialang.org/t/is-it-suggested-to-write-functions-for-io/79718/4 "2022-04-20T07:33:08Z")

</div>

I would have a look at [BenchmarkTools.jl](https://github.com/JuliaCI/BenchmarkTools.jl) then. Just watch out for global variables when benchmarking, see the [docs](https://juliaci.github.io/BenchmarkTools.jl/stable/) for more info on how to use it.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [April 20, 2022, 8:20am UTC](https://discourse.julialang.org/t/is-it-suggested-to-write-functions-for-io/79718/5 "2022-04-20T08:20:07Z")

</div>

> [@Rratic](#):
>
> I see, but I need the exact answer to “which is quicker” partly because I will use it for both cases(somtimes I need String and sometimes `IO` )

Well, I couldn’t answer that precisely because what’s quicker depends on how it’s used and what exactly you mean with that 🙂 Benchmarking your use case is definitely the way to go, but having an API that takes an `IO` that you explicitly print to is (generally) going to be easier to optimize because you don’t create new strings all the time. Wrapping that in a function that passes an `IOBuffer` you then convert to a string will probably be fast.

---

<div class="post-metadata">

**Author:** ![Rratic](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rratic/32/24917_2.png) [@Rratic](https://discourse.julialang.org/u/Rratic)\
**Post date:** [April 20, 2022, 9:20am UTC](https://discourse.julialang.org/t/is-it-suggested-to-write-functions-for-io/79718/6 "2022-04-20T09:20:19Z")

</div>

```julia
julia> @btime A()
  89.172 ns (3 allocations: 160 bytes)
"foo"

julia> @btime B()
  1.500 ns (0 allocations: 0 bytes)
"foo"

julia> io=open("D:/1.txt","w")
IOStream(<file D:/1.txt>)

julia> @btime A($io)
  62.590 ns (0 allocations: 0 bytes)

julia> @btime B($io)
  61.151 ns (0 allocations: 0 bytes)

julia> function encode(obj::Vector)
           l=length(obj)
           if isempty(l)
               return "[]"
           end
           s="[$(obj[1])"
           for i in 2:l
               s*=",$(obj[i])"
           end
           return s*']'
       end
encode (generic function with 1 method)

julia> encode([0,1,2,"foo"])
"[0,1,2,foo]"

julia> @btime encode([0,1,2,"foo"])
  1.440 μs (26 allocations: 1.22 KiB)
"[0,1,2,foo]"

julia> function encode2(io::IO,obj::Vector)
       l=length(obj)
       if isempty(l) print(io,"[]") end
       print(io,"[$(obj[1])")
       for i in 2:l
       print(io,",$(obj[i])")
       end
       print(io,']')
       end
encode2 (generic function with 1 method)

julia> encode2(v::Vector)=sprint(encode2,v)
encode2 (generic function with 2 methods)

julia> @btime encode2([0,1,2,"foo"])
  1.580 μs (25 allocations: 1.27 KiB)
"[0,1,2,foo]"

```

---

<div class="post-metadata">

**Author:** ![Rratic](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rratic/32/24917_2.png) [@Rratic](https://discourse.julialang.org/u/Rratic)\
**Post date:** [April 20, 2022, 9:38am UTC](https://discourse.julialang.org/t/is-it-suggested-to-write-functions-for-io/79718/7 "2022-04-20T09:38:55Z")

</div>

The benchmark above somehow shows that using `::IO` (for writing) should be more likely to be chosen when it’s complicated.
