It seems natural that contracts that are touched infrequently should cost more to execute than the contracts that are touched frequently. In the worst case scenario, if contract is called once every few years it seem unfair and unnecessary if we attempt to guarantee it the same privileges as to the contract that is getting executed many times a second.
On the other hand, it is clear that contract execution performance can be greatly increased if the contract was always pre-loaded into memory (because it avoids unpacking and loading Wasmer module, and disk costs).
Additionally, dApps that are frequently used are only the ones that care about high TPS.
I suggest we consider modifying the protocol to track the top-1000 contracts for each epoch, based on the amount of burnt gas. The list of the hashes of these contracts would be published together with list of new validators at the end of the epoch. Clients then would store these contracts in memory and charge a reduced fee for their execution.
Additionally, we would identify these contracts by their hash of their code, as opposed to account id. So if there are multiple NEP-141 accounts, their total burnt gas will be added up together.
If we include the cost of loading the contract into the total burnt gas, when computing top-1000 contracts then we might end up with certain “borderline” contracts leaving and reentering top-1000 contracts every epoch in oscillation fashion. This might not be a big problem though.