From 92f1656b7149def92aa11a26c900ebe3f0597f9c Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Wed, 3 Jul 2019 18:10:36 -0400 Subject: [PATCH] Add a fast overload for `fieldcount(Tuple{...})` Add an overload for `Base.fieldcount` for Tuples, since we can determine it much more cheaply than for other types. Currently `fieldcount(Tuple{Int, Float32})`, for example, cannot const fold, and thus requires a runtime length check of the types array. Before this change, on Julia 1.1 this took around 6ns, and on master, it's currently 13ns: ```julia julia> @btime fieldcount(Tuple{Int,Int}) 13.043 ns (0 allocations: 0 bytes) 2 ``` After this change, this is instantaneous: ```julia julia> @btime fieldcount(Tuple{Int,Int}) 0.025 ns (0 allocations: 0 bytes) 2 ``` Of course, the tradeoff is that the dispatch becomes more expensive if we have to do a dynamic dispatch: ```julia julia> randtup() = tuple(1:rand(1:10)...) randtup (generic function with 1 method) julia> f() = fieldcount(typeof(randtup()))+1 f (generic function with 1 method) julia> @btime f() 680.552 ns (8 allocations: 438 bytes) 5 julia> Base.fieldcount(@nospecialize t::Type{T}) where T<:Tuple{Vararg{Any,N}} where N = N julia> @btime f() 703.386 ns (8 allocations: 428 bytes) 7 ``` --- base/reflection.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/base/reflection.jl b/base/reflection.jl index 6385103b8fb02..e8a709db49648 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -686,6 +686,10 @@ function fieldcount(@nospecialize t) end return length(t.name.names) end +# Add an overload for Tuples, where we can determine this much more cheaply than for other types. +function fieldcount(@nospecialize t::Type{T}) where T<:Tuple{Vararg{Any,N}} where N + N +end """ fieldtypes(T::Type)