Closed tgrecojs closed 6 days ago
write ava test macro that facilitates communication of (a varying number of) offers to the tribblesAirdrop contract over the course of different, user-defined intervals.
keyring
intervalLength
offerFreqequency
@dckc below are the contents of a test file i have in my local agoric-sdk.
I've added some comments within the code that I hope you find useful... and here are some additional points highlighting aspects of the code, how it's run.
yarn test ./test/performance.test.ts
from the context of my copy of the agoric-sdk. The directory is agoric-sdk/airdrop-testing
.// @ts-nocheck
import anyTest from '@endo/ses-ava/prepare-endo.js';
import type { TestFn } from 'ava';
import { makeDoOffer } from '../tools/e2e-tools.js';
import { commonSetup, SetupContextWithWallets } from './support.js';
import { addresses, defaultMerkleObject } from './airdrop-data/oct21-keys.js';
const test = anyTest as TestFn<SetupContextWithWallets>;
const contractName = 'tribblesAirdrop';
const contractBuilder =
'../packages/builders/scripts/testing/start-tribbles-airdrop.js';
import SEED_PHRASES from './phrases.js';
const generateInt = x => () => Math.floor(Math.random() * (x + 1));
const createTestTier = generateInt(4); // ?
test.before(async t => {
const {
deleteTestKeys,
startContract,
// setupSpecificKeys should be used upon first pass of tests
// adds keys to keyring, therefore it doesn't need to be called additional times (doing so will cause an error)
setupSpecificKeys,
vstorageClient,
...setup
} = await commonSetup(t);
// example usage. comment out after first run
await setupSpecificKeys(SEED_PHRASES);
await startContract(contractName, contractBuilder);
const [brands] = await Promise.all([
vstorageClient.queryData('published.agoricNames.brand'),
]);
t.context = {
...setup,
istBrand: Object.fromEntries(brands).IST,
vstorageClient,
deleteTestKeys,
};
});
const defaultAcct = {
pubkey: { key: '' },
address: 'agoric12d3fault',
};
const makeOfferArgs = (account = defaultAcct) => ({
key: account.pubkey.key,
proof: defaultMerkleObject.getProof(account),
address: account.address,
tier: createTestTier(),
});
const makeDoOfferHandler = async (
useChain,
currentAccount,
wallet,
feeAmount,
) => {
console.log(
'claiming for account::',
currentAccount.address,
'pubkey',
currentAccount.pubkey,
);
const doOffer = makeDoOffer(wallet);
const startTime = performance.now();
await doOffer({
id: `offer-${Date.now()}`,
invitationSpec: {
source: 'agoricContract',
instancePath: [contractName],
callPipe: [['makeClaimTokensInvitation']],
},
offerArgs: makeOfferArgs(currentAccount),
proposal: {
give: {
Fee: feeAmount,
},
},
});
const duration = performance.now() - startTime;
return { ...currentAccount, duration, wallet };
};
const claimAirdropMacro = async (t, addressRange = [0, 1], delay) => {
const [start, end] = addressRange;
const { provisionSmartWallet, useChain, istBrand } = t.context;
const durations = [];
// Make multiple API calls with the specified delay
for (let i = start; i < end; i++) {
const currentAccount = defaultMerkleObject.getAccount(addresses[i]);
console.log('Curren Acccount', currentAccount);
console.log('Current iteration::', i);
const wallet = await provisionSmartWallet(currentAccount.address, {
IST: 1000n,
BLD: 50n,
});
// picking off duration and address
// this can be used to inspect the validity of offer results, however it comes at the expense
// of a failing test halting execution & destroying duration data
const { duration, address } = await makeDoOfferHandler(
useChain,
currentAccount,
wallet,
harden({ value: 5n, brand: istBrand }),
);
durations.push(duration);
// Assert that the response matches the expected output
console.group('######### CHECKING TRIBBLES ALLOCATION #######');
console.log('----------------------------------');
console.log('currentAccount.address ::::', address);
console.log('----------------------------------');
// Wait for the specified delay before making the next call
await new Promise(resolve => setTimeout(resolve, delay));
}
return durations;
};
test.serial(
'makeClaimTokensInvitation offers ### start: accounts[20] || end: accounts[24] ### offer interval: 10000ms',
async t => {
const claimRange = [20, 24];
const durations = await claimAirdropMacro(t, claimRange, 10000);
t.deepEqual(durations.length === 4, true);
t.log('Durations for all calls', durations);
console.group('################ START DURATIONS logger ##############');
console.log('----------------------------------------');
console.log('durations ::::', durations);
console.log('----------------------------------------');
console.log('claimRange ::::', claimRange);
console.log('--------------- END DURATIONS logger -------------------');
console.groupEnd();
},
);
test.serial(
'makeClaimTokensInvitation offers ### start: accounts[25] || end: accounts[29] ### offer interval: 5000ms',
async t => {
const claimRange = [25, 29];
const durations = await claimAirdropMacro(t, claimRange, 5000);
t.deepEqual(durations.length === 4, true);
t.log('Durations for all calls', durations);
console.group('################ START DURATIONS logger ##############');
console.log('----------------------------------------');
console.log('durations ::::', durations);
console.log('----------------------------------------');
console.log('claimRange ::::', claimRange);
console.log('--------------- END DURATIONS logger -------------------');
console.groupEnd();
},
);
commented updated per conversation with @dckc
Times for offer to finish executing in milliseconds, ordered from 1st offer to last.
Times for offer to finish executing in milliseconds, ordered from 1st offer to last.
@dckc updated to contain test results
I conducted performance testing of smart contract interactions on a local Agoric blockchain instance. The tests focused on measuring transaction latency under different request frequencies to assess the system's behavior under various loads.
The Tribbles Airdrop architecture will utilize a Node.js server as an intermediary between the UI and RPC node. This design:
performance.now()
t0
: Immediately before submitting offer to RPC nodet1
: Upon offer resolutiont1 - t0
for each transactioncc @otoole-brendan
@tgrecojs Thanks for sharing above. We discussed usage/projections with Zaki in our sync the other week, it was roughly below:
I'm thinking we need to run scenario D and E above. Could you set that up? I'll run it by @dckc and Warner to get their take too
These look like pretty thorough performance testing results for the local chain case.
I suggest leaving xnet stuff out of scope of this issue, which lets you close this one.
Did you use release v0.0.1 8d9ca6e of the contract? If not, please keep the bundles around and, if you checked in the code, note the git hash.
If you checked in code (however scruffy) to do the testing above, please make a note of the git hash for future reference.
got it @dckc thanks!
Did you use release v0.0.1 https://github.com/hindley-milner-systems/dapp-ertp-airdrop/commit/8d9ca6ec090efbd4ecbfeebe3baa7e695efd3642 of the contract? If not, please keep the bundles around and, if you checked in the code, note the git hash.
I did use this version of the contract for release v0.1.0
I'm about to push up a fix for #121.
The latest release is v0.1.1. One thing to note is that the merkle root is likely different as it was computed using a different set of accounts.
I tried making plots of the raw data. Data points for scenario 1 and 3 are identical. Copy-and-paste problem somewhere? Can you clarify?
@dckc I'm just seeing this now.
thanks for pointing this out as I was operating under the belief that they had produced the same results when inspecting the final measurements. I even mentioned this to @otoole-brendan on slack 😮
my words were something along the lines of "look how insanely consistent these numbers are!" 🤦♂️ I'll get to this first this in the morning.