123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- import * as anchor from "@coral-xyz/anchor";
- import * as token from "@coral-xyz/spl-token";
- import { Bench } from "../target/types/bench";
- import { BenchData, ComputeUnits } from "../scripts/utils";
- describe("Compute units", () => {
- // Configure the client to use the local cluster
- anchor.setProvider(anchor.AnchorProvider.env());
- const program = anchor.workspace.Bench as anchor.Program<Bench>;
- const owner = program.provider.publicKey!;
- let mintPk: anchor.web3.PublicKey;
- let tokenPk: anchor.web3.PublicKey;
- const computeUnits: ComputeUnits = {};
- const measureComputeUnits = async (
- ixName: string,
- options?: Partial<{
- accountCounts: number[];
- generateKeypair: (accountName: string) => anchor.web3.Keypair;
- generatePublicKey: (accountName: string) => anchor.web3.PublicKey;
- }>
- ) => {
- options ??= {};
- options.accountCounts ??= [1, 2, 4, 8];
- options.generateKeypair ??= () => anchor.web3.Keypair.generate();
- for (const accountCount of options.accountCounts) {
- // Check whether the init version of the instruction exists
- const ixNameInit = `${ixName}Init`;
- const hasInitVersion = program.idl.instructions.some((ix) =>
- ix.name.startsWith(ixNameInit)
- );
- const ixNames = [ixName];
- if (hasInitVersion) {
- // Init version has priority
- ixNames.unshift(ixNameInit);
- }
- const accounts: { [key: string]: anchor.web3.PublicKey } = {};
- const signers = [];
- for (const ixName of ixNames) {
- const method =
- `${ixName}${accountCount}` as keyof typeof program.methods;
- // Remove signers when it's not init instruction
- if (ixName !== ixNameInit) {
- signers.splice(0);
- }
- for (const ix of program.idl.instructions) {
- if (ix.name !== method) continue;
- for (const account of ix.accounts) {
- // Only set account keys if it hasn't been set before
- if (accounts[account.name]) {
- continue;
- }
- if (account.name === "payer") {
- accounts[account.name] = owner;
- continue;
- }
- // Skip other accounts to not override Anchor defaults
- if (!account.name.startsWith("account")) {
- continue;
- }
- if (options.generatePublicKey) {
- accounts[account.name] = options.generatePublicKey(account.name);
- continue;
- }
- const keypair = options.generateKeypair(account.name);
- accounts[account.name] = keypair.publicKey;
- if (account.signer) {
- signers.push(keypair);
- }
- }
- }
- // Send tx
- console.log({ method });
- const txHash = await program.methods[method]()
- .accounts(accounts)
- .signers(signers)
- .rpc();
- // Confirm tx
- await program.provider.connection.confirmTransaction(
- txHash,
- "confirmed"
- );
- // Get tx
- const tx = await program.provider.connection.getTransaction(txHash, {
- commitment: "confirmed",
- });
- computeUnits[method] = tx!.meta!.computeUnitsConsumed!;
- }
- }
- };
- before(async () => {
- // Create necessary accounts
- const tokenProgram = token.splTokenProgram({
- provider: anchor.AnchorProvider.local(),
- });
- const tx = new anchor.web3.Transaction();
- // Create mint account
- const mintKp = new anchor.web3.Keypair();
- mintPk = mintKp.publicKey;
- const createMintIx = await tokenProgram.account.mint.createInstruction(
- mintKp
- );
- const initMintIx = await tokenProgram.methods
- .initializeMint2(0, owner, null)
- .accounts({ mint: mintPk })
- .instruction();
- tx.add(createMintIx, initMintIx);
- // Create token account
- const tokenKp = new anchor.web3.Keypair();
- tokenPk = tokenKp.publicKey;
- const createTokenIx = await tokenProgram.account.account.createInstruction(
- tokenKp
- );
- const initTokenIx = await tokenProgram.methods
- .initializeAccount3(owner)
- .accounts({ account: tokenPk, mint: mintPk })
- .instruction();
- tx.add(createTokenIx, initTokenIx);
- await tokenProgram.provider.sendAndConfirm!(tx, [mintKp, tokenKp]);
- });
- it("AccountInfo", async () => {
- await measureComputeUnits("accountInfo");
- });
- it("Account Empty", async () => {
- await measureComputeUnits("accountEmpty");
- });
- it("Account Sized", async () => {
- await measureComputeUnits("accountSized");
- });
- it("Account Unsized", async () => {
- await measureComputeUnits("accountUnsized");
- });
- it("Boxed Account Empty", async () => {
- await measureComputeUnits("boxedAccountEmpty");
- });
- it("Boxed Account Sized", async () => {
- await measureComputeUnits("boxedAccountSized");
- });
- it("Boxed Account Unsized", async () => {
- await measureComputeUnits("boxedAccountUnsized");
- });
- it("Boxed Interface Account Mint", async () => {
- await measureComputeUnits("boxedInterfaceAccountMint", {
- generatePublicKey: () => mintPk,
- });
- });
- it("Boxed Interface Account Token", async () => {
- await measureComputeUnits("boxedInterfaceAccountToken", {
- generatePublicKey: () => tokenPk,
- });
- });
- it("Interface Account Mint", async () => {
- await measureComputeUnits("interfaceAccountMint", {
- generatePublicKey: () => mintPk,
- });
- });
- it("Interface Account Token", async () => {
- await measureComputeUnits("interfaceAccountToken", {
- generatePublicKey: () => tokenPk,
- accountCounts: [1, 2, 4],
- });
- });
- it("Interface", async () => {
- await measureComputeUnits("interface", {
- generatePublicKey: () => token.SPL_TOKEN_PROGRAM_ID,
- });
- });
- it("Program", async () => {
- await measureComputeUnits("program", {
- generatePublicKey: () => anchor.web3.SystemProgram.programId,
- });
- });
- it("Signer", async () => {
- await measureComputeUnits("signer");
- });
- it("SystemAccount", async () => {
- await measureComputeUnits("systemAccount");
- });
- it("UncheckedAccount", async () => {
- await measureComputeUnits("uncheckedAccount");
- });
- after(async () => {
- const bench = await BenchData.open();
- await bench.update({ computeUnits });
- });
- });
|