We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
import { expect } from '@0x/contracts-test-utils'; import { AbiEncoder, BigNumber, NULL_ADDRESS } from '@0x/utils'; import { MethodAbi } from 'ethereum-types'; import { utils } from 'ethers'; // import { utils as ethers5Utils } from 'ethers5'; import _ = require('lodash'); import { performance, PerformanceObserver } from 'perf_hooks'; const percentile = require('percentile'); // tslint:disable-next-line: no-implicit-dependencies import { FastABI } from 'fast-abi'; import { ZERO_AMOUNT } from '../../src/utils/market_operation_utils/constants'; import { getSampleAmounts } from '../../src/utils/market_operation_utils/sampler'; describe.only('Encoder perf', () => { const UNISWAP_V2_SELL_ABI: MethodAbi = { inputs: [ { internalType: 'address', name: 'router', type: 'address', }, { internalType: 'address[]', name: 'path', type: 'address[]', }, { internalType: 'uint256[]', name: 'takerTokenAmounts', type: 'uint256[]', }, ], name: 'sampleSellsFromUniswapV2', outputs: [ { internalType: 'uint256[]', name: 'makerTokenAmounts', type: 'uint256[]', }, ], stateMutability: 'view', type: 'function', }; const KYBER_TUPLE_ABI: MethodAbi = { inputs: [ { name: 'opts', type: 'tuple', components: [ { name: 'reserveOffset', type: 'uint256', }, { name: 'hintHandler', type: 'address', }, { name: 'networkProxy', type: 'address', }, { name: 'weth', type: 'address', }, { name: 'hint', type: 'bytes', }, ], }, { name: 'takerToken', type: 'address', }, { name: 'makerToken', type: 'address', }, { name: 'takerTokenAmounts', type: 'uint256[]', }, ], name: 'sampleSellsFromKyberNetwork', outputs: [ { name: 'reserveId', type: 'bytes32', }, { name: 'hint', type: 'bytes', }, { name: 'makerTokenAmounts', type: 'uint256[]', }, ], stateMutability: 'view', type: 'function', }; const BATCH_CALL_ABI: MethodAbi = { inputs: [ { name: 'callDatas', type: 'bytes[]', }, ], name: 'batchCall', outputs: [ { name: 'callResults', type: 'tuple[]', components: [ { name: 'data', type: 'bytes', }, { name: 'success', type: 'bool', }, ], }, ], stateMutability: 'view', type: 'function', }; const RUST_ENCODER = new FastABI([UNISWAP_V2_SELL_ABI, BATCH_CALL_ABI, KYBER_TUPLE_ABI], { BigNumber }); // tslint:disable: custom-no-magic-numbers const RUNS = 10000; // const RUNS = 1; const ADDRESS_1 = '0x6b175474e89094c44da98b954eedeac495271d0f'; const ADDRESS_2 = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'; let summary: { p25: string; p50: string; p99: string; p100: string }; const perf = (fn: () => void): any => { const wrapped = performance.timerify(fn); const resultsMs: number[] = []; const obs = new PerformanceObserver(list => resultsMs.push(list.getEntries()[0].duration)); obs.observe({ entryTypes: ['function'] }); _.times(RUNS, () => wrapped()); obs.disconnect(); summary = { p25: percentile(25, resultsMs), p50: percentile(50, resultsMs), p99: percentile(99, resultsMs), p100: percentile(100, resultsMs), }; }; before(() => { console.log('Runs:', RUNS); }); beforeEach(() => { summary = { p25: '0', p50: '0', p99: '0', p100: '0' }; }); afterEach(() => { const { p25, p50, p99, p100 } = summary; console.log(`p25: ${p25}ms, p50: ${p50}ms, p99: ${p99}ms, p100: ${p100}ms\n`); }); const TIMEOUT = 360000; const ZERO_EX_ENCODER = new AbiEncoder.Method(UNISWAP_V2_SELL_ABI); const ZERO_EX_UNOPTIMIZED: AbiEncoder.EncodingRules = { shouldOptimize: false, shouldAnnotate: false }; const ZERO_EX_OPTIMIZED: AbiEncoder.EncodingRules = { shouldOptimize: true, shouldAnnotate: false }; const ETHERS_INTERFACE = new utils.Interface([UNISWAP_V2_SELL_ABI]); const ETHERS_ENCODER = ETHERS_INTERFACE.functions[UNISWAP_V2_SELL_ABI.name]; // const ETHERS_5_INTERFACE = new ethers5Utils.Interface([UNISWAP_V2_SELL_ABI]); describe.only('hello', () => { it('node', () => { const f = () => 'hello world'; perf(f); }); it.only('rust', () => { const f = () => FastABI.ping(); perf(f); }); it.only('rust - encode', () => { const params = [ADDRESS_1, [ADDRESS_2], [1, 2, 3]]; const output = RUST_ENCODER.encodeInput('sampleSellsFromUniswapV2', params); }); }); describe.only('Tuple ABI', () => { const ZERO_EX_TUPLE = new AbiEncoder.Method(KYBER_TUPLE_ABI); const params = [ { reserveOffset: ZERO_AMOUNT, hintHandler: NULL_ADDRESS, networkProxy: NULL_ADDRESS, weth: NULL_ADDRESS, hint: '0x', }, ADDRESS_1, ADDRESS_2, getSampleAmounts(new BigNumber(100e6), 13, 1.03), ]; const encoded = ZERO_EX_TUPLE.encode(params, ZERO_EX_UNOPTIMIZED); describe('encode', () => { it('rust', () => { const f = () => RUST_ENCODER.encodeInput('sampleSellsFromKyberNetwork', params); expect(f()).to.eq(encoded); perf(f); }); it('zeroex - optimized', () => { const f = () => ZERO_EX_TUPLE.encode(params, ZERO_EX_OPTIMIZED); perf(f); }); it('zeroex - unoptimized', () => { const f = () => ZERO_EX_TUPLE.encode(params, ZERO_EX_UNOPTIMIZED); perf(f); }); }); describe('decode', () => { it('rust', () => { const f = () => RUST_ENCODER.decodeInput('sampleSellsFromKyberNetwork', encoded); }); }); }); describe('Uniswap ABI', () => { [13, 130].forEach(numSamples => { describe(`${numSamples} input encode`, () => { const params: [string, string[], BigNumber[]] = [ ADDRESS_1, // router [ADDRESS_1, ADDRESS_2, ADDRESS_1], // path getSampleAmounts(new BigNumber(100e6), numSamples, 1.03), ]; it.only('ZeroEx - optimized', () => { const f = () => ZERO_EX_ENCODER.encode(params, ZERO_EX_OPTIMIZED); perf(f); }).timeout(TIMEOUT); it.only('ZeroEx - no optimize', () => { const f = () => ZERO_EX_ENCODER.encode(params, ZERO_EX_UNOPTIMIZED); perf(f); }).timeout(TIMEOUT); it('ZeroEx - BigInt - optimize', () => { const amounts = params[2].map(n => BigInt(n.toString())); const f = () => ZERO_EX_ENCODER.encode([params[0], params[1], amounts], ZERO_EX_OPTIMIZED); perf(f); }).timeout(TIMEOUT); it('ZeroEx - BigInt - no optimize', () => { const amounts = params[2].map(n => BigInt(n.toString())); const f = () => ZERO_EX_ENCODER.encode([params[0], params[1], amounts], ZERO_EX_UNOPTIMIZED); perf(f); }).timeout(TIMEOUT); it.only('rust', () => { const f = () => RUST_ENCODER.encodeInput('sampleSellsFromUniswapV2', params); perf(f); expect(f()).to.eq(ZERO_EX_ENCODER.encode(params, ZERO_EX_UNOPTIMIZED)); }).timeout(TIMEOUT); it.skip('Ethers', () => { const f = () => ETHERS_ENCODER.encode(params); perf(f); }); // it.skip('Ethers 5', () => { // const f = () => ETHERS_5_INTERFACE.encodeFunctionData(UNISWAP_V2_SELL_ABI.name, params); // perf(f); // }).timeout(TIMEOUT); }); describe.only(`${numSamples} input decode`, () => { const params: [string, string[], BigNumber[]] = [ ADDRESS_1, // router [ADDRESS_1, ADDRESS_2, ADDRESS_1], // path getSampleAmounts(new BigNumber(100e6), numSamples, 1.03), ]; const data = ZERO_EX_ENCODER.encode(params, ZERO_EX_UNOPTIMIZED); it('ZeroEx', () => { const f = () => ZERO_EX_ENCODER.decode(data); perf(f); }).timeout(TIMEOUT); it('rust', () => { const f = () => RUST_ENCODER.decodeInput('sampleSellsFromUniswapV2', data); perf(f); }).timeout(TIMEOUT); }); describe.only(`${numSamples} output decode`, () => { const params = getSampleAmounts(new BigNumber(100e6), numSamples, 1.03); const data = ZERO_EX_ENCODER.encodeReturnValues([params], ZERO_EX_UNOPTIMIZED); it('ZeroEx', () => { const f = () => ZERO_EX_ENCODER.decodeReturnValues(data); perf(f); }).timeout(TIMEOUT); it('rust', () => { const f = () => RUST_ENCODER.decodeOutput('sampleSellsFromUniswapV2', data); perf(f); }).timeout(TIMEOUT); }); }); }); describe('BatchCall ABI', () => { [10, 50, 100].forEach(numSamples => { describe.only(`${numSamples} batchCall`, () => { const callParams: [string, string[], BigNumber[]] = [ ADDRESS_1, // router [ADDRESS_1, ADDRESS_2, ADDRESS_1], // path getSampleAmounts(new BigNumber(100e6), 13, 1.03), ]; const encodedBatchCall = ZERO_EX_ENCODER.encode(callParams, ZERO_EX_UNOPTIMIZED); const params = _.times(numSamples, () => encodedBatchCall); const BATCH_CALL_ENCODER = new AbiEncoder.Method(BATCH_CALL_ABI); it('rust', () => { const f = () => RUST_ENCODER.encodeInput('batchCall', [params]); expect(f()).to.eq(BATCH_CALL_ENCODER.encode([params], ZERO_EX_UNOPTIMIZED)); perf(f); }).timeout(TIMEOUT); it('ZeroEx - optimized', () => { const f = () => BATCH_CALL_ENCODER.encode([params], ZERO_EX_OPTIMIZED); perf(f); }).timeout(TIMEOUT); it('ZeroEx - no optimize', () => { const f = () => BATCH_CALL_ENCODER.encode([params], ZERO_EX_UNOPTIMIZED); perf(f); }).timeout(TIMEOUT); }); }); }); });
The text was updated successfully, but these errors were encountered:
No branches or pull requests
The text was updated successfully, but these errors were encountered: