d可替代hasUDA吗

原文

在项目中,我大量使用hasUDA,getUDAs和getSymbolsByUDA.dmd需要大约3.2Gb来编译它,一个dub重新编译需要大约8-14秒.
如下内容,与环境无关:

static if (isSerialisable!member)
{
    import std.path : buildNormalizedPath;

    static if (hasUDA!(this.tupleof[i], Resource))
    {
        member = buildNormalizedPath(state.settings.resourceDirectory, member);
    }
    else static if (hasUDA!(this.tupleof[i], Configuration))
    {
        member = buildNormalizedPath(state.settings.configDirectory, member);
    }
}
private alias allEventHandlerFunctionsInModule =
    Filter!(isSomeFunction, getSymbolsByUDA!(thisModule, IRCEventHandler));
enum isSetupFun(alias T) = (getUDAs!(T, IRCEventHandler)[0]._when == Timing.setup);
enum isEarlyFun(alias T) = (getUDAs!(T, IRCEventHandler)[0]._when == Timing.early);
enum isLateFun(alias T) = (getUDAs!(T, IRCEventHandler)[0]._when == Timing.late);
enum isCleanupFun(alias T) = (getUDAs!(T, IRCEventHandler)[0]._when == Timing.cleanup);
alias hasSpecialTiming = templateOr!(isSetupFun, isEarlyFun, isLateFun, isCleanupFun);
alias isNormalEventHandler = templateNot!hasSpecialTiming;

alias setupFuns = Filter!(isSetupFun, this.allEventHandlerFunctionsInModule);
alias earlyFuns = Filter!(isEarlyFun, this.allEventHandlerFunctionsInModule);
alias lateFuns = Filter!(isLateFun, this.allEventHandlerFunctionsInModule);
alias cleanupFuns = Filter!(isCleanupFun, this.allEventHandlerFunctionsInModule);
alias pluginFuns = Filter!(isNormalEventHandler, this.allEventHandlerFunctionsInModule);

如果hasUDA等很差,可用什么来代替?
我需要它们在编译时工作.只需要求值hasUDAtruefalse,但对getUDAsgetSymbolsByUDA,我需要它们按符号(而不是符号的串名)解析.
我还有别的选择吗?

因此,有个排除关键字将是很好的.但现在,有个更好的方法.在LDC中,构建我整个引擎需要250mb,在DMD中,我没有检查,但也差不多.
这里说,使用udaIndex比使用hasUDAgetUDA更好.
getUDA可简单地更改为:

__traits(getAttributes, yourMemberHere)

许多std.traits实际用,用静如(static if)+别名序列(AliasSeq)Filter!()递归模板.递归模板超重,很慢.

标准库中最好避免递归类型,特别是经常使用时.
那么,如果想构造更好过滤,该怎么做呢?好吧,构造一个索引数组来代替AliasSeq.如果不使用递归模板,就不可能程序化构造AliasSeq.这样就可迭代这些索引了.
需要更多手工操作,但长期运行时效果更好,特别是不想改变反射函数时.

因此,避免过滤,这似乎是主要瓶颈.特别是经常迭代所有成员.最好用单次迭代及使用相同数据.
代码类似如下:

alias setupFuns = Filter!(isSetupFun, this.allEventHandlerFunctionsInModule);
alias earlyFuns = Filter!(isEarlyFun, this.allEventHandlerFunctionsInModule);

///伪码扩展表示
template setupFuns alias pred)
{
    alias Filter = AliasSeq!();
    static foreach (member; Module)
        static if (pred!arg)
            Filter = AliasSeq!(Filter, arg);
}
template earlyFuns(alias pred)
{
    alias Filter = AliasSeq!();
    static foreach (member; Module)
        static if (pred!arg)
            Filter = AliasSeq!(Filter, arg);
}

更好解决办法是:

static foreach(mem; __traits(allMembers, thisModule))
{
    static if(is(typeof(__traits(getMember, thisModule, mem)) == EarlyFunc))
    else static if(is(typeof(__traits(getMember, thisModule, mem)) == LateFunc))

}

这样,避免了多次递归模板,只使用一次反射(迭代一次与迭代n次区别).

posted @   zjh6  阅读(22)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示