Optimize `Linker` setup
Robbepop opened this issue · comments
It was found that in the contracts-pallet
the wasmi::Linker
setup of all the 52 host functions for each call takes up to 30% of the total execution time in test cases where there are only cross-contract calls.
Note: This is to be expected since the contracts-pallet
is not using Wasmi the way the Wasm spec or Wasmi itself are expected to be used where both Engine
and Linker
are long lived entities, whereas Instance
and Store
are rather short-lived entities.
However, due to memory consumption limitations we cannot really change anything about the way the contracts-pallet
inherently uses Wasmi. Therefore we need to optimize wasmi::Linker
when populating it with host functions.
An alternative optimization is to only populate the wasmi::Linker
with those host function calls that are actually used. However, this requires to store some persistent information per uploaded smart contract.
Optimization Possibilities
-
Make
wasmi::Linker::define
and subsets faster: Not sure what is the bottle-neck, yet but if we find one we should work on that. Note that use of atomics is not an issue here since thecontracts-pallet
uses Wasmi within Wasm itself which has no notion of atomics, thus atomics are getting compiled down to non-atomic primitives. -
Introduce new abstractions that allow to pre-populate a
wasmi::Linker
before actually creating aLinker
thus speeding up the population process. This could mean to introduce aHostApi
type which can be populated once and re-used to create newwasmi::Linker
instances. The question is: can we do that? And how much faster can we get? -
Add new
wasmi::Module::new_with_linker
API that takes a&mut wasmi::Linker
and feeds it whenever the parsing notices an import to tell theLinker
that the import is going to be required. This way we could create an emptywasmi::Linker
and only feed it with what the parsedwasmi::Module
actually needs. The big downside to this approach is weights calculation since then thepallet-contracts
needs to charge for every used imported host function per call since that cost is no longer fixed.