是否在同一 WASM 内存中建立块?
这并不一定是一个功能请求或行动呼吁,而是简单地记录了关于这个主题的想法。 无论基底导入哪个区块,它都会调用作为execute_block暴露的运行时 API 函数。在幕后,它将初始化区块的状态,选择并运行每个外部函数,然后完成区块,并且所有这些操作都在同一个 WASM 实例中进行。这意味着所有内存都是持久的,在两次调用之间。简单地说,在on_initialize中对内存的更改将在on_finalize中可见。 然而,与此相对,在构建区块时,每个状态都是其自己的运行时调用:初始化区块将是 一个,应用外部函数将是 另一个。 这意味着 FRAME 或其他运行时代码无法假设内存在调用之间是持久的。有几个原因可能使这种情况是可取的: 1. 根据我对合约的工作经验,有几次我希望内存在调用之间保持不变。 1. https://GitHub.com/paritytech/substrate/issues/9170 这是另一个案例,可能通过其他方式解决,但仍然如此。 1. 在on_initialize和on_finalize之间传递数据,而不触及存储。这在我们需要在on_finalize中执行某些操作时很常见。例如,从列表中删除满足某个条件的 N 个元素。然而,使用on_finalize需要on_initialize返回给on_finalize消耗的权重,这意味着on_initialize将需要查看满足谓词的项数,从而获得 N。然而,尽管on_initialize完成了工作,on_finalize将需要运行相同的代码来决定要删除哪些元素。如果on_initialize能够向on_finalize通知需要删除的项就更好。 1. 这也与将临时存储添加到 Substrate 运行时作为某种主机支持的方式相关,通过自定义子树。似乎将值存储在内存中可以通过更优雅的方式解决此问题,而无需引入临时存储。不过,我不确定是否所有用例都可以通过它覆盖。 这也与 WASM 实例创建开销相关。在最近对 https://GitHub.com/paritytech/substrate/issues/10244 的工作中,我们发现了一个问题:当前的实例调用开销至少为 ≈50µs。如果我们将目标设为 1000 tps,则每个 Polkadot 区块中有 12k 个交易,因此在 cumulus 中,仅在 WASM 实例创建开销上就需要 600ms,无论如何都是相当长的时间。虽然这并不重要,并且可能会在其他地方出现瓶颈,但仍然需要注意。 解决此问题的一种方法是简单地在运行时 API 调用之间保留一个实例,而不是 …
内容来源: paritytech/substrate