Julia - 为什么使用宏 @info 会产生糟糕的 @code_warntype 性能?

Julia - Why using macro @info generates bad @code_warntype performance?

我想知道为什么使用@info 会产生糟糕的 err 变量性能:Any。查看下一个 MWE:

function bad_performance()
    @info "demo"
end



julia> @code_warntype bad_performance()
Variables
  #self#::Core.Compiler.Const(test, false)
  level::Base.CoreLogging.LogLevel
  std_level::Base.CoreLogging.LogLevel
  group::Symbol
  _module::Module
  logger::Union{Nothing, Base.CoreLogging.AbstractLogger}
  id::Symbol
  file::String
  line::Int64
  msg::String
  err::Any

我应该改变什么来避免它,或者我应该忽略来自@code_warntype的这个红色警告?

注意:它还会为记录器变量生成黄色警告。

这是因为您可以创建自己的记录器并将其设置为当前记录器,它使用全局非常量变量。你可以用

更简单地看到同样的现象
julia> printstdout(str) = print(stdout, str)
printstdout (generic function with 1 method)

julia> @code_warntype optimize=true printstdout("hello")
Variables
  #self#::Core.Const(printstdout)
  str::String

Body::Union{Nothing, Int64}
1 ─ %1  = Main.print::Core.Const(print)
│   %2  = Main.stdout::Any
│   %3  = (isa)(%2, Cthulhu.TextWidthLimiter)::Bool
└──       goto #3 if not %3
2 ─ %5  = π (%2, Cthulhu.TextWidthLimiter)
│   %6  = invoke %1(%5::Cthulhu.TextWidthLimiter, _2::String)::Union{Nothing, Int64}
└──       goto #4
3 ─ %8  = Main.print(Main.stdout, str)::Union{Nothing, Int64}
└──       goto #4
4 ┄ %10 = φ (#2 => %6, #3 => %8)::Union{Nothing, Int64}
└──       return %10

虽然

julia> typeof(stdout)
Base.TTY

推断为Any 因为

julia> isconst(Base, :stdout)
false

必须是这样才能允许 redirect_stdout

好消息是糟糕的记录器推断仅在您实际记录时才有意义;如果它被包裹在一个不会被触发的 if 块中,对性能的影响通常是最小的。如果您发现它对您的情况很重要,请将 @info 放入一个单独的函数中,您可以从需要快速的函数中调用它。