JuliaLang / julia

The Julia Programming Language
https://julialang.org/
MIT License
45.45k stars 5.46k forks source link

show(io, x::Int) allocates #41396

Open green-nsk opened 3 years ago

green-nsk commented 3 years ago

The current implementation of show(io, x::Int) converts int to string and then show()s that string. This obviously causes an allocation and suboptimal.

My benchmarks show considerable performance difference:

const iobuf = IOBuffer(fill(UInt8(0), 4000000); truncate = true, maxsize = bufsize)
# 81.694 ns (2 allocations: 96 bytes)
@btime print($iobuf, 123456)
# 25.041 ns (0 allocations: 0 bytes)
@btime print_int($iobuf, 123456)

print_int() here is my version based on the library code, that reuses thread-local buffers, to remove unnecessary allocations.

The same problem exists for printing floats:

# 132.736 ns (2 allocations: 432 bytes)
@btime print($iobuf, 123.456)
# 84.964 ns (0 allocations: 0 bytes)
@btime print_float($iobuf, 123.456)

I have some code that I adapted from the library for my narrow needs. I can prepare a PR if someone is interested enough to review that.

Seelengrab commented 3 years ago

Possible duplicate of #39041

Ah, no, those are different codepaths.

green-nsk commented 3 years ago

Yep, seems unrelated.

To be clear, the allocation issue stems from here: https://github.com/JuliaLang/julia/blob/v1.6.0/base/show.jl#L969 and eventually here: https://github.com/JuliaLang/julia/blob/master/base/intfuncs.jl#L688

As you can see, a new string is allocated for every show() call.

JeffBezanson commented 3 years ago

:+1: Yes, I think this is always worth optimizing.

Seelengrab commented 3 years ago

I've dug around in this code too much, I keep thinking of other unrelated things like #40718 that are in a similar situation

I have some code that I adapted from the library for my narrow needs. I can prepare a PR if someone is interested enough to review that.

Please don't hesitate to open one!

green-nsk commented 3 years ago

Feel free to chip in on that PR