Description
In #46690, I want to deserialize an object on a precompile worker and it is quite important that this is fully precompiled since a lot of precompile workers are spawned and each of these have a separate process and thus they would all need to compile the same code over and over if this isn't the case.
For arbitrary data types, deserialize
has a function that takes ::DataType
and will not get specialized:
julia/stdlib/Serialization/src/Serialization.jl
Line 1468 in aae8c48
As an example workload we can look at the following code
using Serialization
struct MyStruct
x::String
end
s = MyStruct("foo")
io = IOBuffer()
serialize(io, s)
seekstart(io)
@time deserialize(io);
Running that with --trace-compile=stderr
the following precompile statements are emitted from the deserialize
call:
precompile(Tuple{typeof(Serialization.deserialize), Serialization.Serializer{Base.GenericIOBuffer{Array{UInt8, 1}}}, DataType})
However, restarting Julia and executing these before the deserialize
call we can see that the precompile
call for the DataType
fails:
julia> precompile(Tuple{typeof(Serialization.deserialize), Serialization.Serializer{Base.IOStream}, DataType})
false
and the compilation time is still there.
However, if we specialize the function on the data type (as done in 6e0b2da#diff-0fbb91f060d958d93fcf0a101ade4d87b365f3664a409276c591d7faf77acb67) the precompilation statements we get is:
precompile(Tuple{typeof(Serialization.deserialize), Serialization.Serializer{Base.GenericIOBuffer{Array{UInt8, 1}}}, Type{Main.MyStruct}})
the compilation time is then removed:
julia> @time deserialize(io);
0.000014 seconds (14 allocations: 1.148 KiB)
It would be good if the code that is compiled for signatures that are non-concrete could be cached. They clearly are when you run the code since you don't have to compile it for every call.