-
Notifications
You must be signed in to change notification settings - Fork 211
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Create server profiling test (OG-196) The Relay Server currently makes too many RPC calls while operating. This commmit does not change that but creates a test to observe the number of RPC calls per server method. Also, some cleanup.
- Loading branch information
Showing
6 changed files
with
253 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import { HttpProvider } from 'web3-core' | ||
import { JsonRpcPayload, JsonRpcResponse } from 'web3-core-helpers' | ||
|
||
type SendCallback = (error: (Error | null), result?: JsonRpcResponse) => void | ||
|
||
export class ProfilingProvider implements HttpProvider { | ||
private readonly methodsCount = new Map<string, number>() | ||
private _requestsCount = 0 | ||
|
||
provider: HttpProvider | ||
logTraffic: boolean | ||
|
||
get requestsCount (): number { | ||
return this._requestsCount | ||
} | ||
|
||
get connected (): boolean { | ||
return this.provider.connected | ||
} | ||
|
||
get host (): string { | ||
return this.provider.host | ||
} | ||
|
||
constructor (provider: HttpProvider, logTraffic: boolean = false) { | ||
this.provider = provider | ||
this.logTraffic = logTraffic | ||
} | ||
|
||
disconnect (): boolean { | ||
return false | ||
} | ||
|
||
supportsSubscriptions (): boolean { | ||
return false | ||
} | ||
|
||
send (payload: JsonRpcPayload, callback: SendCallback): void { | ||
this._requestsCount++ | ||
const currentCount = this.methodsCount.get(payload.method) ?? 0 | ||
this.methodsCount.set(payload.method, currentCount + 1) | ||
let wrappedCallback: SendCallback = callback | ||
if (this.logTraffic) { | ||
wrappedCallback = function (error: (Error | null), result?: JsonRpcResponse): void { | ||
if (error != null) { | ||
console.log(`<<< error: ${error.message ?? 'null error message'}`) | ||
} | ||
console.log(`<<< result: ${JSON.stringify(result) ?? 'null result'}`) | ||
callback(error, result) | ||
} | ||
console.log(`>>> payload: ${JSON.stringify(payload) ?? 'null result'}`) | ||
} | ||
this.provider.send(payload, wrappedCallback) | ||
} | ||
|
||
reset (): void { | ||
this._requestsCount = 0 | ||
this.methodsCount.clear() | ||
} | ||
|
||
log (): void { | ||
console.log('Profiling Provider Stats:') | ||
new Map([...this.methodsCount.entries()].sort(function ([, count1], [, count2]) { | ||
return count2 - count1 | ||
})).forEach(function (value, key, map) { | ||
console.log(`Method: ${key.padEnd(30)} was called: ${value.toString().padEnd(3)} times`) | ||
}) | ||
console.log(`Total RPC calls: ${this.requestsCount}`) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import { RelayServer } from '../../src/relayserver/RelayServer' | ||
import { | ||
bringUpNewRelay, | ||
LocalhostOne, NewRelayParams, | ||
PrepareRelayRequestOption, | ||
relayTransaction, | ||
RelayTransactionParams | ||
} from './ServerTestUtils' | ||
import { deployHub } from '../TestUtils' | ||
import { configureGSN, GSNConfig } from '../../src/relayclient/GSNConfigurator' | ||
import { ServerDependencies } from '../../src/relayserver/ServerConfigParams' | ||
import ContractInteractor from '../../src/relayclient/ContractInteractor' | ||
import { HttpProvider } from 'web3-core' | ||
import { ProfilingProvider } from '../../src/common/dev/ProfilingProvider' | ||
import { Address } from '../../src/relayclient/types/Aliases' | ||
import { RelayClient } from '../../src/relayclient/RelayClient' | ||
import { GsnRequestType } from '../../src/common/EIP712/TypedRequestData' | ||
|
||
const TestPaymasterEverythingAccepted = artifacts.require('TestPaymasterEverythingAccepted') | ||
const TestRecipient = artifacts.require('TestRecipient') | ||
const StakeManager = artifacts.require('StakeManager') | ||
const Penalizer = artifacts.require('Penalizer') | ||
const Forwarder = artifacts.require('Forwarder') | ||
|
||
contract('RelayServerRequestsProfiling', function ([relayOwner]) { | ||
const callsPerWorker = 63 | ||
const callsPerTransaction = 25 | ||
|
||
let provider: ProfilingProvider | ||
let relayServer: RelayServer | ||
let relayHubAddress: Address | ||
|
||
before(async function () { | ||
const stakeManager = await StakeManager.new() | ||
const penalizer = await Penalizer.new() | ||
const rhub = await deployHub(stakeManager.address, penalizer.address) | ||
relayHubAddress = rhub.address | ||
provider = new ProfilingProvider(web3.currentProvider as HttpProvider) | ||
const newRelayParams: NewRelayParams = { | ||
alertedBlockDelay: 0, | ||
relayHubAddress, | ||
relayOwner, | ||
url: LocalhostOne, | ||
web3, | ||
stakeManager | ||
} | ||
const partialConfig: Partial<GSNConfig> = { | ||
relayHubAddress: rhub.address, | ||
stakeManagerAddress: stakeManager.address | ||
} | ||
const contractInteractor = new ContractInteractor(provider, configureGSN(partialConfig)) | ||
await contractInteractor.init() | ||
const partialDependencies: Partial<ServerDependencies> = { | ||
contractInteractor | ||
} | ||
relayServer = await bringUpNewRelay(newRelayParams, partialConfig, partialDependencies) | ||
}) | ||
|
||
beforeEach(function () { | ||
provider.reset() | ||
}) | ||
|
||
it('should make X requests per block callback', async function () { | ||
const latestBlock = await web3.eth.getBlock('latest') | ||
await relayServer._worker(latestBlock.number) | ||
provider.log() | ||
assert.isAtMost(provider.requestsCount, callsPerWorker) | ||
}) | ||
|
||
describe('relay transaction', function () { | ||
let gasLess: Address | ||
let relayTransactionParams: RelayTransactionParams | ||
let options: PrepareRelayRequestOption | ||
|
||
// TODO: this is a pure copy-paste from Transaction manager test. Create helper code for this! | ||
before(async function () { | ||
gasLess = await web3.eth.personal.newAccount('password') | ||
const forwarder = await Forwarder.new() | ||
// register hub's RelayRequest with forwarder, if not already done. | ||
await forwarder.registerRequestType( | ||
GsnRequestType.typeName, | ||
GsnRequestType.typeSuffix | ||
) | ||
|
||
const forwarderAddress = forwarder.address | ||
|
||
const paymaster = await TestPaymasterEverythingAccepted.new({ gas: 1e7 }) | ||
|
||
const paymasterAddress = paymaster.address | ||
|
||
await paymaster.setRelayHub(relayHubAddress) | ||
await paymaster.setTrustedForwarder(forwarderAddress) | ||
await paymaster.deposit({ value: web3.utils.toWei('1', 'ether') }) | ||
|
||
const sr = await TestRecipient.new(forwarderAddress) | ||
const encodedFunction = sr.contract.methods.emitMessage('hello world').encodeABI() | ||
const recipientAddress = sr.address | ||
const relayClient = new RelayClient((web3.currentProvider as HttpProvider), configureGSN({})) | ||
relayTransactionParams = { | ||
gasLess, | ||
recipientAddress, | ||
relayHubAddress, | ||
encodedFunction, | ||
paymasterData: '', | ||
clientId: '', | ||
forwarderAddress, | ||
paymasterAddress, | ||
relayServer, | ||
web3, | ||
relayClient | ||
} | ||
options = { | ||
from: gasLess, | ||
to: sr.address, | ||
pctRelayFee: 0, | ||
baseRelayFee: '0', | ||
paymaster: paymaster.address | ||
} | ||
}) | ||
|
||
it('should make X requests per relay transaction request', async function () { | ||
await relayTransaction(relayTransactionParams, options) | ||
assert.isAtMost(provider.requestsCount, callsPerTransaction) | ||
}) | ||
}) | ||
}) |
Oops, something went wrong.