将所有“ImmutableMap/List”构建工作卸载到编译时?

问题描述

注意:这并非特定于 minecraft Fabric。我刚接触严格的运行前优化。

我正在为 minecraft 模组编写 API 钩子,允许将各种任务映射到村民的“职业”属性,允许其他模组为自定义职业添加自定义任务。我已经完成了所有后端代码,所以现在我担心优化。

我有一个 ImmutableMap.Builder<VillagerProfession,VillagerTask> 用于存储其他模组添加的任务。问题是,虽然知道永远不会在运行时调用“put”方法,但我不知道编译器是否会调用。显然,由于这是一款游戏,并且模组包中的启动时间已经很长,我想尽可能地优化它,因为每个希望添加新村民的模组都会使用它任务。

这是我当前的“任务注册表”源代码

private static final ImmutableMap.Builder<VillagerProfession,ImmutableList<Pair<Task<? super VillagerEntity>,Integer>>> professionToVillagerTaskBuilder = ImmutableMap.builder();
    
    private static final ImmutableMap<VillagerProfession,Integer>>> professionToVillagerTaskMap;
    
    // The hook that any mods will use in their source code
    public static void addVillagerTasks(VillagerProfession executingProfession,Integer>> task)
    {
        professionToVillagerTaskBuilder.put(executingProfession,task);
    }
    
    //The tasklist retrieval method used at runtime
    static ImmutableList<Pair<Task<? super VillagerEntity>,Integer>> getVillagerRandomTasks(VillagerProfession profession)
    {
        return professionToVillagerTaskMap.get(profession);
    }
    
    static { // probably not the correct way to do this,but it lets me mark the map as final
        professionToVillagerTaskMap = professionToVillagerTaskBuilder.build();
    }

谢谢!

解决方法

简单的回答是:你不能做你想做的事。

问题是,虽然我知道永远不会在运行时调用“put”方法,但我不知道编译器是否会调用。

必须在运行时调用 put 方法才能使您的 mod 有用。当您的代码以可以执行的形式加载时——这就是运行时。这可能是您的 mod 的设置阶段,但它在 JVM 中运行。

如果源代码不包含注册表本身,那么编译器就不能将它翻译成可执行代码;它无法优化它不知道存在的东西。您(开发人员)无法知道将加载哪些 mod,因此编译器无法知道,因此无法对其进行优化或预先计算。这就是您为动态加载代码付出的代价。


至于你贴的代码:它不会工作。

static 块在类加载时执行。将其视为类的构造函数而不是对象。当 mod 可以调用它的任何方法时,必须加载该类,并且它的静态块已经被执行。在从外部调用任何方法之前,您的地图将被设置为空。添加的所有任务将永远留在构建器中,未使用、未见、未爱。

保留建设者。让 mods 添加他们的条目。然后,当所有 mod 加载完成并且游戏开始时,调用 build() 并将结果用作注册表。 (使用您的模组框架提供的任何“游戏开始”挂钩。)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...