You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
julia>struct Foo
b::Tuple{Int, String, Float64}end
julia>functionfoo(f::Foo)
bar(foo=f.b)
end
foo (generic function with 1 method)
julia>@noinlinefunctionbar(; kwargs...)
# println(kwargs)
s =0for (k, v) inpairs(kwargs)
v isa Int && (s = v)
endreturn s
end
bar (generic function with 1 method)
julia>@btimefoo(Foo((1, "hey", 3.14)))
28.989 ns (3 allocations:80 bytes)
0
julia>@code_warntypefoo(Foo((1, "hey", 3.14)))
Body::Int6421 ─ %1= Base.getfield(%%f, :b)::Tuple{Int64,String,Float64} │╻ getproperty
│ %2=new(NamedTuple{(:foo,),Tuple{Tuple{Int64,String,Float64}}}, %1)::NamedTuple{(:foo,),Tuple{Tuple{Int64,String,Float64}}}
│ %3= :(Main.bar)::Core.Compiler.Const(bar, false) │
│ %4=new(Base.Iterators.Pairs{Symbol,Tuple{Int64,String,Float64},Tuple{Symbol},NamedTuple{(:foo,),Tuple{Tuple{Int64,String,Float64}}}}, %2, (:foo,))::Base.Iterators.Pairs{Symbol,Tuple{Int64,String,Float64},Tuple{Symbol},NamedTuple{(:foo,),Tuple{Tuple{Int64,String,Float64}}}}
│ %5= invoke Main.:(#bar#13)(%4::Base.Iterators.Pairs{Symbol,Tuple{Int64,String,Float64},Tuple{Symbol},NamedTuple{(:foo,),Tuple{Tuple{Int64,String,Float64}}}}, %3::Function)::Int64
└── return%5 │
Note in the final @code_warntype how we're both creating new(NamedTuple... as well as new(Base.Iterators.Pairs, while %2 doesn't even end up being used (or eliminated in the @code_llvm).
The text was updated successfully, but these errors were encountered:
Oh, I actually see now that the Base.Iterators.Pairs is being constructed from the NamedTuple object. Is there anything better we can do here to avoid the extra allocations?
JeffBezanson
changed the title
Extra allocations from passing keyword arguments to inner functions
Extra allocations from passing keyword arguments
Jul 18, 2018
This is expected; it's very difficult to optimize away rest keywords (kwargs... in bar). In fact I don't think we can ever eliminate the allocation of any object passed to a @noinline function.
It turns out most of my problem was actually #28147; after commenting out all my @debug statements, I avoid almost all extra allocations of rest keyword args. It was insightful to learn about the "codegen" peculiarities of explicit keyword args vs. rest; i.e. explicit, named keyword arguments that get passed down to another function are better to be explicitly named and passed rather than bundled w/ a generic kwargs... catchall.
Take this example:
Note in the final
@code_warntype
how we're both creatingnew(NamedTuple...
as well asnew(Base.Iterators.Pairs
, while%2
doesn't even end up being used (or eliminated in the@code_llvm
).The text was updated successfully, but these errors were encountered: