Weird memory allocation

The allocation occurs for the simplified code posted in the
gist above even if the called function is defined as

function Jacobianvolume{T<:FESet2Manifold}(self::FEMMBase{T}, J::FFltMat,
            loc::FFltMat, conn::FIntMat, N::FFltMat)::FFlt
            return 1.0
end

The expansion is

Variables:
  #self#::FEMMBaseModule.#Jacobianvolume
  self::FEMMBaseModule.FEMMBase{FESetModule.FESetT3,FEMMBaseModule.#otherdimensionunity}
  J::Array{Float64,2}
  loc::Array{Float64,2}
  conn::Array{Int64,2}
  N::Array{Float64,2}

Body:
  begin 
      return 1.0
  end::Float64

Dispatch doesn’t propagate type info for keywords, so FESetT3 is typed as Any.
Here is the problematic code:

type FESetT3 <: FESet2Manifold
  nfensperfe::FInt
  conn::FIntMat
  label::FIntVec

  function  FESetT3(; conn::FIntMat=[], label =zero(FInt))
    const nfensperfe::FInt  = 3
    @assert (size(conn, 2) == nfensperfe) "Number of nodes per element mismatched"
    # Needs to make a COPY of the input arrays
    self = new(nfensperfe, deepcopy(conn), deepcopy(FInt[]))
    return self
  end
end

This is faster:

  function  FESetT3( conn::FIntMat=[], label =zero(FInt))
# etc.

I leave it for the experts to say whether the inference engine is working properly here. Thanks for the puzzle of the day.

Thank you very much dear Sir, this was bugging me no end.

But, how did you figure it out? Where could you see that there was a type instability? What did you do? Or was there something that bit you too?

Petr

This sort of thing has bit me before - keyword arguments are often tricky. In this case, profiling showed that the time was spent in the loop construct itself rather than the function called there, so I applied code_warntype to run1(), which showed the untyped argument femm in the Jacobianvolume call (hence the expensive logic), preceded by

      fes::Any = $(Expr(:invoke, MethodInstance for (::Core.#kw#Type)(::Array{Any,1}, ::Type{FESetModule.FESetT3}), :($(QuoteNode(Type))), :($(Expr(:invoke, MethodInstance for vector_any(::Any, ::Vararg{Any,N} where N), :(Base.vector_any), :(:conn), :(conn)))), :(Driver.FESetT3))) # line 13:
      femm::Any = (Driver.FEMMBase)(fes::Any)::Union{FEMMBaseModule.FEMMBase, FEMMBaseModule.FEMMBase{_,FEMMBaseModule.#otherdimensionunity} where _} # line 14:

which points to the constructor I am quoting in the edited version of my reply above.

@Ralph_Smith:

Much obliged. Thanks!

Petr