一种让生成函数aware外部依赖并重新生成的技巧


#1
struct AwaredGenFn{F} # F是你的生成函数
end

function (agf::AwaredGenFn{F})(args...) where F
     F(Val(Base.get_world_counter()), args...)
end

function (agf::AwaredGenFn{F})(args...; kwargs...) where F
     F(Val(Base.get_world_counter()), args...; kwargs...)
end

macro awaredgenerated(ex)
    quote
        $AwaredGenFn{($Base.@generated $ex)}()
    end |> esc
end

案例: 数量级提速subtypes


using InteractiveUtils
using BenchmarkTools

my_subtypes = @awaredgenerated function x(world, ::Type{T}) where T
    subtypes(T)
end

@info my_subtypes(Number)

struct S <: Number end
@info my_subtypes(Number)

@btime my_subtypes(Number)
@btime subtypes(Number)
[ Info: Any[Complex, Real]
[ Info: Any[Complex, Real, S]
  3.321 μs (1 allocation: 16 bytes)
  4.688 ms (1044 allocations: 601.17 KiB)

#2

好思路 看起来是通过改变生成函数的参数类型来强制重新运行生成函数

不过对我这种情况好像不太管用…


重新eval一遍函数定义是有效的 很靠谱


#3

只要开销在Base.get_world_counter量级以下(us)都没法用这个,但是改改还能用。。。