You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In heavy usage environments which frequently create temporary bindings for usage during a small period of time, a lot of time is spent running abi.JSON. For example I have a backend microservice that listens for new blocks to be mined, and when new blocks are mined instantiates a variety of different contract bindings.
While profiling this program, 7.2% of the recorded profile was spend running abi.JSON. Because the abi package uses reflection, this can lead to a lot of time parsing ABI definitions. Because thes ABI definitions are declared as const variables, a better solution would be to have an init function that does the ABI parsing once when the corresponding package is initialized.
There are some optimizations a user can implement in their programs, such as attempting to make instantiations of the contract bindings longer lived, however this is not always possible.
Implementation
For the sake of arguments lets consider generating bindings for an ERC20 contract. Each time a binding is instantiated the bindERC20 function is called:
// bindErc20 binds a generic wrapper to an already deployed contract.funcbindErc20(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
parsed, err:=abi.JSON(strings.NewReader(Erc20ABI)) // <---- lots of reflection use <----iferr!=nil {
returnnil, err
}
returnbind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
}
This logic could be reworked such that abi.JSON is moved to an init function, and the program structure could be rewritten to:
var (
parsedABI abi.ABI
)
funcinit() {
varerrerrorparsedABI, err=abi.JSON(strings.NewReader(Erc20ABI))
iferr!=nil {
panic(err) // maybe not use panic?
}
}
// bindErc20 binds a generic wrapper to an already deployed contract.funcbindErc20(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
returnbind.NewBoundContract(address, parsedABI, caller, transactor, filterer), nil
}
I haven't done a lot of work with Golang's templating engine, but I would be willing to take a stab at implementing this
The text was updated successfully, but these errors were encountered:
Rationale
In heavy usage environments which frequently create temporary bindings for usage during a small period of time, a lot of time is spent running
abi.JSON
. For example I have a backend microservice that listens for new blocks to be mined, and when new blocks are mined instantiates a variety of different contract bindings.While profiling this program, 7.2% of the recorded profile was spend running
abi.JSON
. Because theabi
package uses reflection, this can lead to a lot of time parsing ABI definitions. Because thes ABI definitions are declared asconst
variables, a better solution would be to have aninit
function that does the ABI parsing once when the corresponding package is initialized.There are some optimizations a user can implement in their programs, such as attempting to make instantiations of the contract bindings longer lived, however this is not always possible.
Implementation
For the sake of arguments lets consider generating bindings for an ERC20 contract. Each time a binding is instantiated the
bindERC20
function is called:This logic could be reworked such that
abi.JSON
is moved to an init function, and the program structure could be rewritten to:I haven't done a lot of work with Golang's templating engine, but I would be willing to take a stab at implementing this
The text was updated successfully, but these errors were encountered: