欧陆风云4吧 关注:333,047贴子:10,260,019

【伪技术】MOD开发进阶课:运行速度与资源管理

只看楼主收藏回复

占楼()


IP属地:湖北来自iPhone客户端1楼2023-12-26 14:46回复
    本文的草稿早在一年多以前和AB汉化组/ABE制作组的几位群友聊天时就写好了,然而本鸽沉迷群友的pf网团…


    IP属地:湖北来自iPhone客户端2楼2023-12-26 14:48
    回复
      文:(bilibili)1onepower/(贴吧)我只玩1次方
      本文的目标读者是MOD制作者,或者真的很想改善你玩的mod的性能的人。
      本文技术程度较高,并不全是像一般的EU MOD制作一样属于无门槛内容。一般来说推荐计算机科学本科大二及以上,或相当水平者阅读。此外为了运用本文的知识,你应该具有基本的英语阅读能力。


      IP属地:湖北来自iPhone客户端3楼2023-12-26 14:51
      回复
        1. 到底是什么在拖慢我的游戏:profiling tool
        任何近期的EU4版本(1.30+)游戏都已经内置有性能分析工具。
        Eu4_profiling.exe就是以性能分析模式启动,启动时会自动应用当前启动器选定的播放集。通常玩游戏时不要用它,因为性能分析工具本身的运行也会拖慢游戏。


        IP属地:湖北来自iPhone客户端4楼2023-12-26 14:54
        收起回复
          这属于一个内部开发工具,其功能比较复杂,但对于本文的目的和话题来说其实只要掌握一个功能就够了,也就是控制台命令dump_script_profiling
          以性能分析模式启动后,后台程序会像gdb分析C++编译的exe文件一样实时分析游戏内的所有数据。对每一个决议、事件、触发器,或者其他任何东西,记录了它们所占用主程的总时间,平均每次访问用时,以及精确到每一行的访问次数。


          IP属地:湖北来自iPhone客户端5楼2023-12-26 14:57
          回复
            让游戏运行一段时间(看海或者玩都行),直到你觉得取到了足够充分的测试样本(比如20年),打开控制台输入dump_script_profiling,就会把截止到此刻为止的记录写进C:\Users\你的用户名\Documents\Paradox Interactive\Europa Universalis IV\logs目录下的profiling.log文件。
            (这里故意没有配图,以促使读者自己试验)


            IP属地:湖北来自iPhone客户端6楼2023-12-26 15:00
            回复
              值得注意的是,这个分析器只计算有效运行时间,如果游戏暂停、游戏的一些无法更改的性能占用项(如动画和音乐)、以及进程切换时的损耗不会统计。但我们仍可以根据性能占用比例来估算其影响,一个进程如果频繁被频繁调用,它产生的损耗也会大致成比例增加。


              IP属地:湖北来自iPhone客户端7楼2023-12-26 15:02
              回复
                让我们看一眼这个文件长什么样:它有上万行并且包括着巨量的缩进树,展示着每一个游戏进程的每一个程序单元的资源占用情况。
                文件一共有6列,Time表示每次这个单元的被访问后,返回的平均时长;Hits表示这个单元被访问的次数;Total T表示以上两者的乘积,即这个单元的总用时;Root表示这个单元的用时占这个单元所在的树的根节点的总用时的比例;Parent表示这个单元的用时占这个单元的母节点用时的比例。一般来说,我们最关心的还是total T,尤其是根节点的total T。
                但这个文件几乎不具有可读性(缩进很不整齐,而且不能排序),因此我们可能还需要一个小小的辅助程序,几行代码即可。可以参考我下面这个,也可以用你习惯的语言或方法随手写一个。


                IP属地:湖北来自iPhone客户端8楼2023-12-26 15:04
                回复
                  那么我们随手分析一下战争前夜+战争前夜拓展(均为2022.10.19工坊版本),取observer模式开5速运行了大约两年,在11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz 上,主进程有效运行了193.226秒,数据如下:


                  IP属地:湖北来自iPhone客户端9楼2023-12-26 15:06
                  回复
                    2. EU4的性能逻辑
                    我们找到了这个模组环境下性能占用前20的根节点,那么就让我们来看看这些节点占用这么多资源究竟合不合理,哪些是确实需要,哪些是制作者写得不够优化。
                    首先看第一个close_foreign_trade.allow,它的意思是close_foreign_trade这个决议的allow也就是,在决议出现在面板之后,能否点它的生效条件。这个根节点在我们193秒的测试样例中一共占用了主进程5.432秒的时间,占用了整个游戏大约2.8%的有效运算量。这个决议并不是AB或者ABE加入的,而是原版游戏的。(在今天的1.36版本似乎早就没了)
                    如图所示,意思是说如果一个中华科技组的国家的视野里有一个西欧科技组的国家,就可以点这个闭关锁国的决议,以外交和科研debuff为代价换取重商主义和国内贸易竞争力的增加(效果没有截图进来)。这个决议值不值得占用整个游戏2.8%的资源呢,我想答案很难是肯定的。


                    IP属地:湖北来自iPhone客户端10楼2023-12-26 15:11
                    回复
                      这个决议为什么要占用如此之多的资源呢?让我们来仔细看看它的profiling log。
                      我们可以看到,在allow的5432ms用时中,有5401ms都是在处理子节点any_known_country,这个子节点占用了根节点99.43%的运算时间。剩下的31ms是在扫过这个决议的名称和框架。这个树并没有延展到any_known_country的下面那个条件mil=3,这里涉及到一个重要的、非常重要的、无比重要的、本文最重要的概念(《编译原理》的第一堂课大约就会涉及):如果X是布尔条件,且是若干布尔条件组成的逻辑式,那么计算机在扫过整个逻辑式的过程中一旦足以判断X的真假,就不会继续扫过X剩下的部分。
                      我们暂且简称为黄金法则。


                      IP属地:湖北来自iPhone客户端11楼2023-12-26 15:15
                      回复
                        在这个例子中,我们只是从1444年开始跑了三分钟五速,显然不会有任何中华科技组的国家看到任何西欧科技组的国家,因此这个allow的第一条就不可能判定为真。因此它下面那一条也就从来没有运行过。
                        也许细心的读者会提问:在实际游戏中,你把鼠标放在一个决议条件上,即使第一条是X,他也还是会显示后面的条件是V还是X呀!这也是一个很常见的编程技巧:只在需要的时候计算。在游戏中,系统对于决议只会判断此时能不能执行(能执行会出左上角提示,或者告诉AI执行),至于具体是什么原因不能执行?等玩家把鼠标放上去的时候再算!游戏中每时每刻都要对每个国家运算,而会把鼠标放上去的只有玩家,会放上去的时间恐怕连总时间的千分之一都没有,因此我们就’几乎’彻底规避了后面这条数据的运算!


                        IP属地:湖北来自iPhone客户端12楼2023-12-26 15:18
                        回复
                          当然,说了这么多,我们只是介绍了两条EU4的引擎已经为我们做好的重要优化,到底为什么close_foreign_trade会占用大量资源我们还没开始谈,那让我们回到这个话题。
                          Any_known_country要占用5401ms,主要是因为我们在这一行代码中以O(n^2)的形式对所有国家进行了遍历:我们对于每一个中华科技组的国家,我们都要遍历所有国家,一个个看它们是否在该国视野里,是否是西方科技组,是否在贸易节点上有交集。这个算法实在是太糟糕了!
                          我们可以看到,technology_group这个节点在这个根节点下被调用了11481389次,3分钟内这一行代码运行了1148万次,检查了这么多次某国是否是西方科技组,因此不得不占用了整个游戏2.8%的资源。
                          为了便于读者理解,我们再解释一下1148万次是怎么来的。中华科技组的国家我们就假定有40个,全球所有国家我们假定有500个,因此每更新一次这个决议的条件,我们就要运行20000次科技组检查。1148万次大约指游戏内这个决议更新了500多次,我们知道决议的allow是每天检查的(游戏内体感:决议达到条件后不需要过月就能点),这和我们说的游戏运行了两年基本吻合(误差应该是来自于tag数目估算不准确)。


                          IP属地:湖北来自iPhone客户端13楼2023-12-26 15:23
                          回复
                            贴吧跟qq头像不一样 没认出你


                            IP属地:天津来自Android客户端14楼2023-12-26 15:30
                            回复
                              讲点触发修正 trigger_modifier


                              IP属地:四川来自Android客户端15楼2023-12-26 15:53
                              回复