Skip to content
New issue

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

chore: run benchmarking utility in devnet environment #3166

Merged
merged 33 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
02f6067
chore: added devnet config
maschad Sep 13, 2024
3a664c4
Merge branch 'master' into mc/test/add-benchmarks-devnet
maschad Sep 13, 2024
3f53e84
chore: updated lockfile
maschad Sep 13, 2024
2e38db3
docs: add changeset
maschad Sep 13, 2024
2592c90
chore: use pyth large contract + update test config
maschad Sep 13, 2024
5bd8e74
test: testing with 10 iterations per bench
maschad Sep 16, 2024
466f0b8
Merge branch 'master' into mc/test/add-benchmarks-devnet
maschad Sep 16, 2024
6a5b867
test: update contract interaction test
maschad Sep 16, 2024
89a2f48
chore: wallet method updates
maschad Sep 17, 2024
12af6da
Merge branch 'master' into mc/test/add-benchmarks-devnet
maschad Sep 17, 2024
7d2389c
test: add console logs for wallet addresses in CI
maschad Sep 17, 2024
aae74db
test: add more debug logs...
maschad Sep 17, 2024
e510839
test: attempt using static deploy method
maschad Sep 17, 2024
3998316
chore: reduce contract calls for test
maschad Sep 17, 2024
deb5f77
test: removing problematic tests
maschad Sep 17, 2024
d559940
test: only loop local node tests
maschad Sep 18, 2024
ab23f26
test: update cost estimation loop
maschad Sep 18, 2024
03bb4be
test: update contract read calls
maschad Sep 18, 2024
535145d
chore: refactor benchmarking tests
maschad Sep 18, 2024
26f53ef
ci: update workflows
maschad Sep 18, 2024
50aad4c
Merge branch 'master' into mc/test/add-benchmarks-devnet
maschad Sep 18, 2024
aea62fb
chore: refactoring + cleanup
maschad Sep 19, 2024
386cb73
Merge branch 'master' into mc/test/add-benchmarks-devnet
maschad Sep 19, 2024
2b3047c
chore: update to large contract factory
maschad Sep 19, 2024
af76ec6
lint: forc formatting
maschad Sep 19, 2024
4fcf577
Merge branch 'master' into mc/test/add-benchmarks-devnet
maschad Sep 20, 2024
4ad4ce1
Merge branch 'master' into mc/test/add-benchmarks-devnet
maschad Sep 24, 2024
38920e3
Merge branch 'master' into mc/test/add-benchmarks-devnet
maschad Sep 25, 2024
c25f012
Merge branch 'master' into mc/test/add-benchmarks-devnet
maschad Sep 26, 2024
be5f2d3
Merge branch 'master' into mc/test/add-benchmarks-devnet
maschad Sep 27, 2024
be9151d
chore: remove private key
maschad Sep 27, 2024
fc6ab5d
Merge branch 'next' into mc/test/add-benchmarks-devnet
maschad Sep 27, 2024
3aee69e
Merge branch 'next' into mc/test/add-benchmarks-devnet
maschad Oct 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/ninety-carpets-watch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@internal/benchmarks": minor
---

chore: run benchmarking utility in devnet environment
32 changes: 32 additions & 0 deletions .github/workflows/bench-testnet.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: "Bench Devnet"

on:
# Remove this before merging, we only want devnet tests on master
arboleya marked this conversation as resolved.
Show resolved Hide resolved
pull_request:
branches:
- master
push:
branches:
- master
- release/*

jobs:
benchmarks:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: CI Setup
uses: ./.github/actions/test-setup

- name: Pretest
run: pnpm pretest

- name: Run Node benchmarks
uses: CodSpeedHQ/action@v3
with:
run: pnpm bench:node
token: ${{ secrets.CODSPEED_TOKEN }}
env:
DEVNET_WALLET_PVT_KEY: ${{ secrets.DEVNET_WALLET_PVT_KEY }}
4 changes: 3 additions & 1 deletion .github/workflows/bench.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
name: Benchmarks
on:
pull_request:
push:
maschad marked this conversation as resolved.
Show resolved Hide resolved
branches:
- master
push:
branches-ignore:
- master

jobs:
benchmarks:
Expand Down
3 changes: 2 additions & 1 deletion internal/benchmarks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
},
"license": "Apache-2.0",
"dependencies": {
"fuels": "workspace:*"
"fuels": "workspace:*",
"@internal/utils": "workspace:*"
},
"version": "1.0.1"
}
11 changes: 11 additions & 0 deletions internal/benchmarks/src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { DEVNET_NETWORK_URL } from '@internal/utils';
import { TransactionType } from 'fuels';

export const DEVNET_CONFIG = {
maschad marked this conversation as resolved.
Show resolved Hide resolved
networkUrl: DEVNET_NETWORK_URL,
faucetUrl: `https://faucet-devnet.fuel.network/`,
txIds: {
[TransactionType.Upgrade]: '0xe2c03044fe708e9b112027881baf9f892e6b64a630a629998922c1cab918c094',
[TransactionType.Upload]: '0x94bc2a189b8211796c8fe5b9c6b67624fe97d2007e104bf1b30739944f43bd73',
},
};
39 changes: 26 additions & 13 deletions internal/benchmarks/src/contract-interaction.bench.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
/* eslint-disable import/no-extraneous-dependencies */

import type { WalletUnlocked } from 'fuels';
import { bn } from 'fuels';
import { WalletUnlocked, bn, Provider } from 'fuels';
import { launchTestNode, TestAssetId } from 'fuels/test-utils';
import { bench } from 'vitest';

import type { CounterContract, CallTestContract } from '../test/typegen/contracts';
import { CounterContractFactory, CallTestContractFactory } from '../test/typegen/contracts';

import { DEVNET_CONFIG } from './config';
/**
* @group node
* @group browser
Expand All @@ -16,20 +17,32 @@ describe('Contract Interaction Benchmarks', () => {
let callTestContract: CallTestContract;
let wallet: WalletUnlocked;
let cleanup: () => void;
beforeEach(async () => {
const launched = await launchTestNode({
contractsConfigs: [{ factory: CounterContractFactory }, { factory: CallTestContractFactory }],

if (process.env.DEVNET_WALLET_PVT_KEY !== undefined) {
beforeAll(async () => {
const { networkUrl } = DEVNET_CONFIG;
const provider = await Provider.create(networkUrl);
wallet = new WalletUnlocked(process.env.DEVNET_WALLET_PVT_KEY as string, provider);
});
} else {
beforeEach(async () => {
const launched = await launchTestNode({
contractsConfigs: [
{ factory: CounterContractFactory },
{ factory: CallTestContractFactory },
],
});

cleanup = launched.cleanup;
contract = launched.contracts[0];
callTestContract = launched.contracts[1];
wallet = launched.wallets[0];
});
cleanup = launched.cleanup;
contract = launched.contracts[0];
callTestContract = launched.contracts[1];
wallet = launched.wallets[0];
});

afterEach(() => {
cleanup();
});
afterEach(() => {
cleanup();
});
}

bench('should successfully execute a contract read function', async () => {
const tx = await contract.functions.get_count().call();
Expand Down
218 changes: 128 additions & 90 deletions internal/benchmarks/src/cost-estimation.bench.ts
Original file line number Diff line number Diff line change
@@ -1,134 +1,172 @@
/* eslint-disable import/no-extraneous-dependencies */

import type { TransferParams, Provider } from 'fuels';
import { ScriptTransactionRequest, Wallet } from 'fuels';
import type { TransferParams, WalletUnlocked } from 'fuels';
import { Wallet, Provider, ScriptTransactionRequest } from 'fuels';
import { launchTestNode, TestAssetId } from 'fuels/test-utils';
import { bench } from 'vitest';

import type { CallTestContract } from '../test/typegen/contracts';
import { CallTestContractFactory } from '../test/typegen/contracts';

import { DEVNET_CONFIG } from './config';

/**
* @group node
* @group browser
*/
describe('Cost Estimation Benchmarks', () => {
let contract: CallTestContract;
let provider: Provider;
let request: ScriptTransactionRequest;
let recipient: WalletUnlocked;
let receiver1: WalletUnlocked;
let receiver2: WalletUnlocked;
let receiver3: WalletUnlocked;
let sender: WalletUnlocked;

let cleanup: () => void;
beforeEach(async () => {
const launched = await launchTestNode({
contractsConfigs: [{ factory: CallTestContractFactory }],

const setup = (testProvider: Provider) => {
request = new ScriptTransactionRequest({ gasLimit: 1000000 });

recipient = Wallet.generate({
provider: testProvider,
});
receiver1 = Wallet.generate({
provider: testProvider,
});
receiver2 = Wallet.generate({
provider: testProvider,
});
receiver3 = Wallet.generate({
provider: testProvider,
});
sender = Wallet.fromPrivateKey(
'0x30bb0bc68f5d2ec3b523cee5a65503031b40679d9c72280cd8088c2cfbc34e38',
testProvider
);
};

cleanup = launched.cleanup;
contract = launched.contracts[0];
provider = contract.provider;
});
if (process.env.DEVNET_WALLET_PVT_KEY !== undefined) {
beforeAll(async () => {
const { networkUrl } = DEVNET_CONFIG;
provider = await Provider.create(networkUrl);

afterEach(() => {
cleanup();
});
setup(provider);
});
} else {
beforeEach(async () => {
const launched = await launchTestNode({
contractsConfigs: [{ factory: CallTestContractFactory }],
});

cleanup = launched.cleanup;
contract = launched.contracts[0];
provider = contract.provider;

setup(provider);
});

afterEach(() => {
cleanup();
});
}

bench(
'should successfully get transaction cost estimate for a single contract call',
'should successfully get transaction cost estimate for a single contract call done 10 times',
async () => {
const cost = await contract.functions
.return_context_amount()
.callParams({
for (let i = 0; i < 10; i++) {
const cost = await contract.functions
.return_context_amount()
.callParams({
forward: [100, contract.provider.getBaseAssetId()],
})
.getTransactionCost();

expect(cost.minFee).toBeDefined();
expect(cost.maxFee).toBeDefined();
expect(cost.gasPrice).toBeDefined();
expect(cost.gasUsed).toBeDefined();
expect(cost.gasPrice).toBeDefined();
}
}
);

bench('should successfully get transaction cost estimate for multi contract calls', async () => {
for (let i = 0; i < 10; i++) {
const invocationScope = contract.multiCall([
contract.functions.return_context_amount().callParams({
forward: [100, contract.provider.getBaseAssetId()],
})
.getTransactionCost();
}),
contract.functions.return_context_amount().callParams({
forward: [200, TestAssetId.A.value],
}),
]);

const cost = await invocationScope.getTransactionCost();

expect(cost.minFee).toBeDefined();
expect(cost.maxFee).toBeDefined();
expect(cost.gasPrice).toBeDefined();
expect(cost.gasUsed).toBeDefined();
expect(cost.gasPrice).toBeDefined();
}
);

bench('should successfully get transaction cost estimate for multi contract calls', async () => {
const invocationScope = contract.multiCall([
contract.functions.return_context_amount().callParams({
forward: [100, contract.provider.getBaseAssetId()],
}),
contract.functions.return_context_amount().callParams({
forward: [200, TestAssetId.A.value],
}),
]);

const cost = await invocationScope.getTransactionCost();

expect(cost.minFee).toBeDefined();
expect(cost.maxFee).toBeDefined();
expect(cost.gasPrice).toBeDefined();
expect(cost.gasUsed).toBeDefined();
expect(cost.gasPrice).toBeDefined();
});

bench('should successfully get transaction cost estimate for a single transfer', async () => {
const request = new ScriptTransactionRequest({ gasLimit: 1000000 });
for (let i = 0; i < 10; i++) {
request.addCoinOutput(recipient.address, 10, provider.getBaseAssetId());

const recipient = Wallet.generate({
provider,
});
const sender = Wallet.fromPrivateKey(
'0x30bb0bc68f5d2ec3b523cee5a65503031b40679d9c72280cd8088c2cfbc34e38',
provider
);

request.addCoinOutput(recipient.address, 10, provider.getBaseAssetId());
const cost = await sender.getTransactionCost(request);

const cost = await sender.getTransactionCost(request);

expect(cost.minFee).toBeDefined();
expect(cost.maxFee).toBeDefined();
expect(cost.gasPrice).toBeDefined();
expect(cost.gasUsed).toBeDefined();
expect(cost.gasPrice).toBeDefined();
expect(cost.minFee).toBeDefined();
expect(cost.maxFee).toBeDefined();
expect(cost.gasPrice).toBeDefined();
expect(cost.gasUsed).toBeDefined();
expect(cost.gasPrice).toBeDefined();
}
});

bench('should successfully get transaction cost estimate for a batch transfer', async () => {
const receiver1 = Wallet.generate({ provider });
const receiver2 = Wallet.generate({ provider });
const receiver3 = Wallet.generate({ provider });

const amountToTransfer1 = 989;
const amountToTransfer2 = 699;
const amountToTransfer3 = 122;

const transferParams: TransferParams[] = [
{
destination: receiver1.address,
amount: amountToTransfer1,
assetId: provider.getBaseAssetId(),
},
{ destination: receiver2.address, amount: amountToTransfer2, assetId: TestAssetId.A.value },
{ destination: receiver3.address, amount: amountToTransfer3, assetId: TestAssetId.B.value },
];

const cost = await contract.functions
.sum(40, 50)
.addBatchTransfer(transferParams)
.getTransactionCost();

expect(cost.minFee).toBeDefined();
expect(cost.maxFee).toBeDefined();
expect(cost.gasPrice).toBeDefined();
expect(cost.gasUsed).toBeDefined();
expect(cost.gasPrice).toBeDefined();
for (let i = 0; i < 10; i++) {
const amountToTransfer1 = 989;
const amountToTransfer2 = 699;
const amountToTransfer3 = 122;

const transferParams: TransferParams[] = [
{
destination: receiver1.address,
amount: amountToTransfer1,
assetId: provider.getBaseAssetId(),
},
{ destination: receiver2.address, amount: amountToTransfer2, assetId: TestAssetId.A.value },
{ destination: receiver3.address, amount: amountToTransfer3, assetId: TestAssetId.B.value },
];

const cost = await contract.functions
.sum(40, 50)
.addBatchTransfer(transferParams)
.getTransactionCost();

expect(cost.minFee).toBeDefined();
expect(cost.maxFee).toBeDefined();
expect(cost.gasPrice).toBeDefined();
expect(cost.gasUsed).toBeDefined();
expect(cost.gasPrice).toBeDefined();
}
});

it('should successfully get transaction cost estimate for a mint', async () => {
const subId = '0x4a778acfad1abc155a009dc976d2cf0db6197d3d360194d74b1fb92b96986b00';
it('should successfully get transaction cost estimate for a mint 10 times', async () => {
for (let i = 0; i < 10; i++) {
const subId = '0x4a778acfad1abc155a009dc976d2cf0db6197d3d360194d74b1fb92b96986b00';

const cost = await contract.functions.mint_coins(subId, 1_000).getTransactionCost();
const cost = await contract.functions.mint_coins(subId, 1_000).getTransactionCost();

expect(cost.minFee).toBeDefined();
expect(cost.maxFee).toBeDefined();
expect(cost.gasPrice).toBeDefined();
expect(cost.gasUsed).toBeDefined();
expect(cost.gasPrice).toBeDefined();
expect(cost.minFee).toBeDefined();
expect(cost.maxFee).toBeDefined();
expect(cost.gasPrice).toBeDefined();
expect(cost.gasUsed).toBeDefined();
expect(cost.gasPrice).toBeDefined();
}
});
});
Loading
Loading