问题
在 Screeps 中,Memory 是很重要的存在,它让信息可以在Tick与Tick之间保存状态。但是每个Tick对Memory的第一次引用都会触发Memory的反序列化,我们来看一下官方原文。
可见,每次都进行反序列化,对CPU的开销是比较大的,官方也告诉我们,实际上使用RawMemory是一种更好的方式,但这需要我们自己去进行设定,并且这对很多人来说很难。
但接下来的方案您可以参考一下,在继续说之前我需要问自己几个问题。
注意:Memroy存在的意义是什么?
它让信息可以在Tick与Tick之间保存状态
注意:还有什么可以跨Tick之间保存状态?
没错,global,但是global会定时清空 这个问题在之后会得到解决
那么,我们只需要让 RawMemory 做到Tick与Tick之间保持状态就可以了,我们并不需要再去写一个RawMemory序列/反序列模块。
But, How?
- 我们让序列化的数据,保存在 RawMemory0 (以下简称Raw0)中
- 让global储存我们的反序列化数据,并建立Proxy监听
- 在Raw1(以下简称Cache)中记录好每个tick对global的更改,当变化时,写入到Cache
-
每当global清空时,立即从Raw0反序列化数据,通过合并Cache中的修改来还原数据的最后状态并恢复数据到global
如此一来,Cache中只会储存被经常修改的数据,例如状态机、坐标位置、寻路缓存等小量动态数据,这部分数据只有在Proxy监听到修改时会得到序列化与反序列化的同步更新,耗时取决于在一个global周期你做了多少事情;Raw0中的数据通常多的是大量静态数据,这部分数据的序列化与反序列化频率只取决于global被清空的频率。
Absolutely,我们在对每个Tick的修改进行监听时使用到了Proxy,您当然可以在Proxy中实现更加优美的反序列化逻辑。
Absolutely2,您可以在Raw0与Cache(Raw1)合并时加入Raw2,Raw3等,来扩容或者分类,并设置他们的合并逻辑。
关于global挂载这里有仙术,可以参考
https://www.jianshu.com/p/c6413d67893b