Penalty associated with arrays of differently typed objects of identical structure


#1

Is there any way to eliminate the following penalty in future versions of Julia? In particular, I am talking about the cases when the types of elements in an array are different but this type difference does not change the “bit encoding” of the objects because the types just vary in an informational type parameter which is not used in the field type definitions.

julia> mutable struct T1{S}
           a::Int
       end

julia> f!(a::Vector{T1}, b::Vector{T1}) = (for i in 1:length(a) a[i].a = b[i].a; end)
f! (generic function with 1 method)

julia> a = [T1{i}(i) for i in 1:10];

julia> b = [T1{-i}(-i) for i in 1:10];

julia> using BenchmarkTools

julia> @btime f!(a, b)
  716.314 ns (0 allocations: 0 bytes)

julia> mutable struct T2
           a::Int
       end

julia> f!(a::Vector{T2}, b::Vector{T2}) = (for i in 1:length(a) a[i].a = b[i].a; end)
f! (generic function with 2 methods)

julia> a = [T2(i) for i in 1:10];

julia> b = [T2(-i) for i in 1:10];

julia> @btime f!(a, b)
  24.797 ns (0 allocations: 0 bytes)

#2

Not at the moment although it’s certainly a potential future optimization. You could remove the apparently nominal type parameters: if it makes sense to store a heterogenous collection of these that suggests that the parameters i are more data than metadata. Otherwise, if you really need objects of different types, you can always store the homogenous data in the array with i values and construct the objects on the fly. Of course the compiler still doesn’t know the type since it’s a runtime property, so you may still get performed issues there. Note that the latter approach is really just the former solution in disguise.


#3

Thanks for your response. It’s not like I really need this feature, but it was more of a why not question. If a real use case comes up, I will ping this thread again.


#4

For mutable structs you can’t actually do better in terms of representation since they need to be boxed anyway, but for immutables the representation could be optimized in this case.


#5

Just a random idea, would having 2 types associated with any object: dispatch type and data type, be feasible or help with this in any way? Dispatch type could be used to decide which method to call and data type could be used for type inference and to compile the specialized functions for the input parameters after a specific method has been selected. Sorry if this sounds like nonsense!

Edit: on second thought, that does sound like nonsense, so nevermind!


#6

This is something that would help in a lot of the low-level sort of stuff I frequently do.
I may have a parameterized type, with only one field, always with the same type, that I need to be handled in different ways based on the parameters, and also, in many cases the methods are identical, no matter what the parameters.