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

[DRAFT] - [perf] - wasm optimisations #6

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
27 changes: 27 additions & 0 deletions benchmark/__tests__/results-store.js
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lack of error handling:
If there is an error while reading or writing the file, it can cause the program to crash without any clear indication. You should wrap file operations in try-catch blocks to gracefully handle potential file system errors.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, you're right. Thanks for pointing that out.

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import fs from "fs";
import path from "path";

const resultsFilePath = path.resolve("temp-all-test-results.json");

function readExistingResults() {
if (fs.existsSync(resultsFilePath)) {
const fileContent = fs.readFileSync(resultsFilePath, "utf-8");
return JSON.parse(fileContent);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JSON.parse() call could throw an error if the file contents are malformed or not valid JSON. It's good to wrap this in a try-catch block to handle such cases.

}
return {};
}

export function saveResults(newResults) {
const existingResults = readExistingResults();
const combinedResults = { ...existingResults, ...newResults };
fs.writeFileSync(resultsFilePath, JSON.stringify(combinedResults, null, 2));
}

export function addTestResults(testName, result) {
if (process.env.GENERATE_REPORT === "true") {
const tempResults = {};
tempResults[testName] = result;

saveResults(tempResults);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we use this function anywhere else seems like it is only used in this one place. Maybe we don't need it?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's true, I will remove it and move the code to addTestResults. Thanks

}
}
92 changes: 16 additions & 76 deletions benchmark/__tests__/test-deploy-contract.ava.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import { Worker } from "near-workspaces";
import test from "ava";
import {
formatGas,
gasBreakdown,
logGasBreakdown,
logGasDetail,
} from "./util.js";
import { generateGasObject, logTestResults } from "./util.js";
import { addTestResults } from "./results-store.js";

test.before(async (t) => {
// Init the worker and start a Sandbox server
Expand Down Expand Up @@ -47,49 +43,21 @@ test("JS promise batch deploy contract and call", async (t) => {
let r = await bob.callRaw(callerContract, "deploy_contract", "", {
gas: "300 Tgas",
});
// console.log(JSON.stringify(r, null, 2));

let deployed = callerContract.getSubAccount("a");

t.deepEqual(JSON.parse(Buffer.from(r.result.status.SuccessValue, "base64")), {
currentAccountId: deployed.accountId,
signerAccountId: bob.accountId,
predecessorAccountId: callerContract.accountId,
input: "abc",
});

t.log(
"Gas used to convert transaction to receipt: ",
formatGas(r.result.transaction_outcome.outcome.gas_burnt)
);
t.log(
"Gas used to execute the receipt (actual contract call): ",
formatGas(r.result.receipts_outcome[0].outcome.gas_burnt)
);
let map = gasBreakdown(r.result.receipts_outcome[0].outcome);
logGasBreakdown(map, t);
t.log(
"Gas used to execute the cross contract call: ",
formatGas(r.result.receipts_outcome[1].outcome.gas_burnt)
);
map = gasBreakdown(r.result.receipts_outcome[1].outcome);
logGasBreakdown(map, t);
t.log(
"Gas used to refund unused gas for cross contract call: ",
formatGas(r.result.receipts_outcome[2].outcome.gas_burnt)
);
t.log(
"Gas used to refund unused gas: ",
formatGas(r.result.receipts_outcome[3].outcome.gas_burnt)
);
t.log(
"Total gas used: ",
formatGas(
r.result.transaction_outcome.outcome.gas_burnt +
r.result.receipts_outcome[0].outcome.gas_burnt +
r.result.receipts_outcome[1].outcome.gas_burnt +
r.result.receipts_outcome[2].outcome.gas_burnt +
r.result.receipts_outcome[3].outcome.gas_burnt
)
);
logTestResults(r);

const gasObject = generateGasObject(r);

addTestResults("JS_promise_batch_deploy_contract_and_call", gasObject);
});

test("RS promise batch deploy contract and call", async (t) => {
Expand All @@ -98,47 +66,19 @@ test("RS promise batch deploy contract and call", async (t) => {
let r = await bob.callRaw(callerContractRs, "deploy_contract", "", {
gas: "300 Tgas",
});
// console.log(JSON.stringify(r, null, 2));

let deployed = callerContractRs.getSubAccount("a");

t.deepEqual(JSON.parse(Buffer.from(r.result.status.SuccessValue, "base64")), {
currentAccountId: deployed.accountId,
signerAccountId: bob.accountId,
predecessorAccountId: callerContractRs.accountId,
input: "abc",
});

t.log(
"Gas used to convert transaction to receipt: ",
formatGas(r.result.transaction_outcome.outcome.gas_burnt)
);
t.log(
"Gas used to execute the receipt (actual contract call): ",
formatGas(r.result.receipts_outcome[0].outcome.gas_burnt)
);
let map = gasBreakdown(r.result.receipts_outcome[0].outcome);
logGasBreakdown(map, t);
t.log(
"Gas used to execute the cross contract call: ",
formatGas(r.result.receipts_outcome[1].outcome.gas_burnt)
);
map = gasBreakdown(r.result.receipts_outcome[1].outcome);
logGasBreakdown(map, t);
t.log(
"Gas used to refund unused gas for cross contract call: ",
formatGas(r.result.receipts_outcome[2].outcome.gas_burnt)
);
t.log(
"Gas used to refund unused gas: ",
formatGas(r.result.receipts_outcome[3].outcome.gas_burnt)
);
t.log(
"Total gas used: ",
formatGas(
r.result.transaction_outcome.outcome.gas_burnt +
r.result.receipts_outcome[0].outcome.gas_burnt +
r.result.receipts_outcome[1].outcome.gas_burnt +
r.result.receipts_outcome[2].outcome.gas_burnt +
r.result.receipts_outcome[3].outcome.gas_burnt
)
);
logTestResults(r);

const gasObject = generateGasObject(r);

addTestResults("RS_promise_batch_deploy_contract_and_call", gasObject);
});
50 changes: 42 additions & 8 deletions benchmark/__tests__/test-expensive-calc.ava.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { Worker } from "near-workspaces";
import test from "ava";
import { logGasDetail } from "./util.js";
import { generateMinimalGasObject, logTestResults } from "./util.js";
import { addTestResults } from "./results-store.js";

test.before(async (t) => {
// Init the worker and start a Sandbox server
const worker = await Worker.init();

// Prepare sandbox for tests, create accounts, deploy contracts, etx.
// Prepare sandbox for tests, create accounts, deploy contracts, etc.
const root = worker.rootAccount;

// Deploy the test contract.
Expand Down Expand Up @@ -35,14 +36,25 @@ test("JS expensive contract, iterate 100 times", async (t) => {
let r = await bob.callRaw(expensiveContract, "expensive", { n: 100 });

t.is(r.result.status.SuccessValue, "LTUw");
logGasDetail(r, t);

logTestResults(r);

const gasObject = generateMinimalGasObject(r);

addTestResults("JS_expensive_contract_100_times", gasObject);
});

test("RS expensive contract. iterate 100 times", async (t) => {
const { bob, expensiveContractRs } = t.context.accounts;
let r = await bob.callRaw(expensiveContractRs, "expensive", { n: 100 });

t.is(r.result.status.SuccessValue, "LTUw");
logGasDetail(r, t);

logTestResults(r);

const gasObject = generateMinimalGasObject(r);

addTestResults("RS_expensive_contract_100_times", gasObject);
});

test("JS expensive contract, iterate 10000 times", async (t) => {
Expand All @@ -55,14 +67,25 @@ test("JS expensive contract, iterate 10000 times", async (t) => {
);

t.is(r.result.status.SuccessValue, "LTUwMDA=");
logGasDetail(r, t);

logTestResults(r);

const gasObject = generateMinimalGasObject(r);

addTestResults("JS_expensive_contract_10000_times", gasObject);
});

test("RS expensive contract. iterate 10000 times", async (t) => {
const { bob, expensiveContractRs } = t.context.accounts;
let r = await bob.callRaw(expensiveContractRs, "expensive", { n: 10000 });

t.is(r.result.status.SuccessValue, "LTUwMDA=");
logGasDetail(r, t);

logTestResults(r);

const gasObject = generateMinimalGasObject(r);

addTestResults("RS_expensive_contract_10000_times", gasObject);
});

test("JS expensive contract, iterate 20000 times", async (t) => {
Expand All @@ -75,12 +98,23 @@ test("JS expensive contract, iterate 20000 times", async (t) => {
);

t.is(r.result.status.SuccessValue, "LTEwMDAw");
logGasDetail(r, t);

logTestResults(r);

const gasObject = generateMinimalGasObject(r);

addTestResults("JS_expensive_contract_20000_times", gasObject);
});

test("RS expensive contract. iterate 20000 times", async (t) => {
const { bob, expensiveContractRs } = t.context.accounts;
let r = await bob.callRaw(expensiveContractRs, "expensive", { n: 20000 });

t.is(r.result.status.SuccessValue, "LTEwMDAw");
logGasDetail(r, t);

logTestResults(r);

const gasObject = generateMinimalGasObject(r);

addTestResults("RS_expensive_contract_20000_times", gasObject);
});
15 changes: 12 additions & 3 deletions benchmark/__tests__/test-highlevel-collection.ava.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Worker } from "near-workspaces";
import test from "ava";
import { logGasDetail } from "./util.js";
import { generateMinimalGasObject, logTestResults } from "./util.js";
import { addTestResults } from "./results-store.js";

test.before(async (t) => {
// Init the worker and start a Sandbox server
Expand Down Expand Up @@ -50,7 +51,11 @@ test("JS highlevel collection contract", async (t) => {
});

t.is(r.result.status.SuccessValue, "");
logGasDetail(r, t);
logTestResults(r);

const gasObject = generateMinimalGasObject(r);

addTestResults("JS_highlevel_collection_contract", gasObject);
});

test("RS highlevel collection contract", async (t) => {
Expand All @@ -68,5 +73,9 @@ test("RS highlevel collection contract", async (t) => {
value: "d".repeat(100),
});
t.is(r.result.status.SuccessValue, "");
logGasDetail(r, t);
logTestResults(r);

const gasObject = generateMinimalGasObject(r);

addTestResults("RS_highlevel_collection_contract", gasObject);
});
15 changes: 12 additions & 3 deletions benchmark/__tests__/test-highlevel-minimal.ava.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Worker } from "near-workspaces";
import test from "ava";
import { logGasDetail } from "./util.js";
import { generateMinimalGasObject, logTestResults } from "./util.js";
import { addTestResults } from "./results-store.js";

test.before(async (t) => {
// Init the worker and start a Sandbox server
Expand Down Expand Up @@ -39,13 +40,21 @@ test("JS highlevel minimal contract", async (t) => {
let r = await bob.callRaw(highlevelContract, "empty", "");

t.is(r.result.status.SuccessValue, "");
logGasDetail(r, t);
logTestResults(r);

const gasObject = generateMinimalGasObject(r);

addTestResults("JS_highlevel_minimal_contract", gasObject);
});

test("RS highlevel minimal contract", async (t) => {
const { bob, highlevelContractRs } = t.context.accounts;
let r = await bob.callRaw(highlevelContractRs, "empty", "");

t.is(r.result.status.SuccessValue, "");
logGasDetail(r, t);
logTestResults(r);

const gasObject = generateMinimalGasObject(r);

addTestResults("RS_highlevel_minimal_contract", gasObject);
});
17 changes: 13 additions & 4 deletions benchmark/__tests__/test-lowlevel-api.ava.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Worker } from "near-workspaces";
import test from "ava";
import { logGasDetail } from "./util.js";
import { generateMinimalGasObject, logTestResults } from "./util.js";
import { addTestResults } from "./results-store.js";

test.before(async (t) => {
// Init the worker and start a Sandbox server
Expand Down Expand Up @@ -35,15 +36,23 @@ test("JS lowlevel API contract", async (t) => {
let r = await bob.callRaw(lowlevelContract, "lowlevel_storage_write", "");

t.is(r.result.status.SuccessValue, "");
logGasDetail(r, t);
logTestResults(r);

const gasObject = generateMinimalGasObject(r);

addTestResults("JS_lowlevel_API_contract", gasObject);
});

test("RS lowlevel API contract", async (t) => {
const { bob, lowlevelContractRs } = t.context.accounts;
let r = await bob.callRaw(lowlevelContractRs, "lowlevel_storage_write", "");

t.is(r.result.status.SuccessValue, "");
logGasDetail(r, t);
logTestResults(r);

const gasObject = generateMinimalGasObject(r);

addTestResults("RS_lowlevel_API_contract", gasObject);
});

test("JS lowlevel API contract, call many", async (t) => {
Expand All @@ -55,5 +64,5 @@ test("JS lowlevel API contract, call many", async (t) => {
);

t.is(r.result.status.SuccessValue, "");
logGasDetail(r, t);
logTestResults(r);
});
15 changes: 12 additions & 3 deletions benchmark/__tests__/test-lowlevel-minimal.ava.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Worker } from "near-workspaces";
import test from "ava";
import { logGasDetail } from "./util.js";
import { generateMinimalGasObject, logTestResults } from "./util.js";
import { addTestResults } from "./results-store.js";

test.before(async (t) => {
// Init the worker and start a Sandbox server
Expand Down Expand Up @@ -35,13 +36,21 @@ test("JS lowlevel minimal contract", async (t) => {
let r = await bob.callRaw(lowlevelContract, "empty", "");

t.is(r.result.status.SuccessValue, "");
logGasDetail(r, t);
logTestResults(r);

const gasObject = generateMinimalGasObject(r);

addTestResults("JS_lowlevel_minimal_contract", gasObject);
});

test("RS lowlevel minimal contract", async (t) => {
const { bob, lowlevelContractRs } = t.context.accounts;
let r = await bob.callRaw(lowlevelContractRs, "empty", "");

t.is(r.result.status.SuccessValue, "");
logGasDetail(r, t);
logTestResults(r);

const gasObject = generateMinimalGasObject(r);

addTestResults("RS_lowlevel_minimal_contract", gasObject);
});
Loading
Loading