perf: add option to use fast-copy library for deep copying object #114

This commit is contained in:
ppedziwiatr
2022-03-08 17:23:20 +01:00
committed by Piotr Pędziwiatr
parent 39af94599f
commit 04a4683357
7 changed files with 29 additions and 71 deletions

View File

@@ -57,6 +57,7 @@
"arweave-multihost": "^0.1.0", "arweave-multihost": "^0.1.0",
"axios": "^0.21.4", "axios": "^0.21.4",
"bignumber.js": "^9.0.1", "bignumber.js": "^9.0.1",
"fast-copy": "^2.1.1",
"json-beautify": "^1.1.1", "json-beautify": "^1.1.1",
"knex": "^0.95.14", "knex": "^0.95.14",
"lodash": "^4.17.21", "lodash": "^4.17.21",
@@ -69,7 +70,7 @@
"devDependencies": { "devDependencies": {
"@types/cheerio": "^0.22.30", "@types/cheerio": "^0.22.30",
"@types/jest": "^27.0.1", "@types/jest": "^27.0.1",
"@types/node": "^16.7.1", "@types/node": "^17.0.21",
"@typescript-eslint/eslint-plugin": "^4.29.2", "@typescript-eslint/eslint-plugin": "^4.29.2",
"@typescript-eslint/parser": "^4.29.2", "@typescript-eslint/parser": "^4.29.2",
"arlocal": "1.1.22", "arlocal": "1.1.22",

View File

@@ -96,6 +96,8 @@ export class DefaultEvaluationOptions implements EvaluationOptions {
sequencerAddress = 'https://gateway.redstone.finance/'; sequencerAddress = 'https://gateway.redstone.finance/';
gasLimit = Number.MAX_SAFE_INTEGER; gasLimit = Number.MAX_SAFE_INTEGER;
useFastCopy = false;
} }
// an interface for the contract EvaluationOptions - can be used to change the behaviour of some of the features. // an interface for the contract EvaluationOptions - can be used to change the behaviour of some of the features.
@@ -143,4 +145,10 @@ export interface EvaluationOptions {
sequencerAddress: string; sequencerAddress: string;
gasLimit: number; gasLimit: number;
// Whether fast-copy library should be used during the state evaluation
// https://github.com/planttheidea/fast-copy#isstrict
// it's much faster (e.g. almost twice for the SJ3l7474UHh3Dw6dWVT1bzsJ-8JvOewtGoDdOecWIZo contract)
// but not yet fully tested - so exposing it as an option (with default to false)
useFastCopy: boolean;
} }

View File

@@ -49,7 +49,7 @@ export class ContractHandlerApi<State> implements HandlerApi<State> {
try { try {
const { interaction, interactionTx, currentTx } = interactionData; const { interaction, interactionTx, currentTx } = interactionData;
const stateCopy = deepCopy(currentResult.state); const stateCopy = deepCopy(currentResult.state, executionContext.evaluationOptions.useFastCopy);
this.swGlobal._activeTx = interactionTx; this.swGlobal._activeTx = interactionTx;
const handler = this.contractFunction(this.swGlobal, BigNumber, clarity, contractLogger) as HandlerFunction< const handler = this.contractFunction(this.swGlobal, BigNumber, clarity, contractLogger) as HandlerFunction<

View File

@@ -68,8 +68,6 @@ export abstract class DefaultStateEvaluator implements StateEvaluator {
`Evaluating state for ${contractDefinition.txId} [${missingInteractions.length} non-cached of ${sortedInteractions.length} all]` `Evaluating state for ${contractDefinition.txId} [${missingInteractions.length} non-cached of ${sortedInteractions.length} all]`
); );
this.logger.trace('Base state:', baseState.state);
let errorMessage = null; let errorMessage = null;
let lastConfirmedTxState: { tx: GQLNodeInterface; state: EvalStateResult<State> } = null; let lastConfirmedTxState: { tx: GQLNodeInterface; state: EvalStateResult<State> } = null;

View File

@@ -1,12 +1,13 @@
/* eslint-disable */ /* eslint-disable */
import cloneDeep from 'lodash/cloneDeep'; import cloneDeep from 'lodash/cloneDeep';
import copy from "fast-copy";
export const sleep = (ms: number): Promise<void> => { export const sleep = (ms: number): Promise<void> => {
return new Promise((resolve) => setTimeout(resolve, ms)); return new Promise((resolve) => setTimeout(resolve, ms));
}; };
export const deepCopy = (input: unknown): any => { export const deepCopy = (input: unknown, useFastCopy = false): any => {
return cloneDeep(input); return useFastCopy ? copy(input) : cloneDeep(input);
}; };
export const mapReplacer = (key: unknown, value: unknown) => { export const mapReplacer = (key: unknown, value: unknown) => {

View File

@@ -20,9 +20,9 @@ const logger = LoggerFactory.INST.create('Contract');
//LoggerFactory.use(new TsLogFactory()); //LoggerFactory.use(new TsLogFactory());
LoggerFactory.INST.logLevel('error'); LoggerFactory.INST.logLevel('error');
//LoggerFactory.INST.logLevel('info', 'Contract'); LoggerFactory.INST.logLevel('info', 'Contract');
//LoggerFactory.INST.logLevel('debug', 'DefaultStateEvaluator'); //LoggerFactory.INST.logLevel('debug', 'DefaultStateEvaluator');
//LoggerFactory.INST.logLevel('error', 'CacheableStateEvaluator'); //LoggerFactory.INST.logLevel('debug', 'CacheableStateEvaluator');
async function main() { async function main() {
printTestInfo(); printTestInfo();
@@ -52,71 +52,18 @@ async function main() {
const koi_source = fs.readFileSync(path.join(__dirname, 'data', 'koi-source.js'), "utf-8"); const koi_source = fs.readFileSync(path.join(__dirname, 'data', 'koi-source.js'), "utf-8");
const smartweave = SmartWeaveNodeFactory.memCachedBased(arweave) const smartweave = SmartWeaveNodeFactory.fileCachedBased(arweave, 'data')
.setInteractionsLoader( .setInteractionsLoader(
new RedstoneGatewayInteractionsLoader('https://gateway.redstone.finance') new RedstoneGatewayInteractionsLoader('https://gateway.redstone.finance')
) )
.overwriteSource({ .build();
["egfnrQFu-xDNgl1x04HlH6-wGKcHVKMF7U5Nsc-1USA"]: "export async function handle (state, action) {\n" +
" const puzzles = state.puzzles\n" +
" const input = action.input\n" +
" const caller = action.caller\n" +
"\n" +
" if (input.function === 'create') {\n" +
" const solution_hash = input.solution_hash\n" +
" const file_id = input.file_id\n" +
"\n" +
" if (!solution_hash) {\n" +
" throw new ContractError('No solution hash provided')\n" +
" }\n" +
"\n" +
" if (!file_id) {\n" +
" throw new ContractError('No file id specified')\n" +
" }\n" +
"\n" +
" if (solution_hash in puzzles) {\n" +
" throw new ContractError('Puzzle already exists')\n" +
" } else {\n" +
" puzzles[solution_hash] = {\n" +
" \"file_id\": file_id,\n" +
" \"creator\": caller,\n" +
" \"winner\": null\n" +
" }\n" +
" }\n" +
"\n" +
" return { state }\n" +
" }\n" +
"\n" +
" if (input.function === 'solve') {\n" +
" const solution = input.solution\n" +
" const solution_hash = input.solution_hash\n" +
"\n" +
" if (solution_hash in puzzles) {\n" +
" const solution_buffer = SmartWeave.arweave.utils.stringToBuffer(solution)\n" +
" const calculated_hash =\n" +
" SmartWeave.arweave.utils.bufferTob64Url(\n" +
" await SmartWeave.arweave.utils.crypto.hash(solution_buffer)\n" +
" )\n" +
" if (calculated_hash === solution_hash){\n" +
" puzzles[solution_hash].winner = caller\n" +
" }\n" +
" } else {\n" +
" throw new ContractError('Puzzle not found')\n" +
" }\n" +
"\n" +
" return { state }\n" +
" }\n" +
"\n" +
" throw new ContractError(`No function supplied or function not recognised: \"${input.function}\"`)\n" +
"}\n",
});
const jwk = readJSON('../redstone-node/.secrets/redstone-jwk.json'); const jwk = readJSON('../redstone-node/.secrets/redstone-jwk.json');
const contract = smartweave const contract = smartweave
.contract("egfnrQFu-xDNgl1x04HlH6-wGKcHVKMF7U5Nsc-1USA") .contract(PIANITY_CONTRACT)
.setEvaluationOptions({ .setEvaluationOptions({
sequencerAddress: 'http://localhost:5666/', sequencerAddress: 'http://localhost:5666/',
updateCacheForEachInteraction: false useFastCopy: true
}) })
.connect(jwk); .connect(jwk);
/* const bundledInteraction = await contract.bundleInteraction({ /* const bundledInteraction = await contract.bundleInteraction({
@@ -133,8 +80,6 @@ async function main() {
fs.writeFileSync(path.join(__dirname, 'data', 'koi-proper-state_2.json'), stringify(state)); fs.writeFileSync(path.join(__dirname, 'data', 'koi-proper-state_2.json'), stringify(state));
logger.info("State", state);
const heapUsedAfter = Math.round((process.memoryUsage().heapUsed / 1024 / 1024) * 100) / 100; const heapUsedAfter = Math.round((process.memoryUsage().heapUsed / 1024 / 1024) * 100) / 100;
const rssUsedAfter = Math.round((process.memoryUsage().rss / 1024 / 1024) * 100) / 100; const rssUsedAfter = Math.round((process.memoryUsage().rss / 1024 / 1024) * 100) / 100;
logger.warn('Heap used in MB', { logger.warn('Heap used in MB', {

View File

@@ -1425,10 +1425,10 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.46.tgz#7e49dee4c54fd19584e6a9e0da5f3dc2e9136bc7" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.46.tgz#7e49dee4c54fd19584e6a9e0da5f3dc2e9136bc7"
integrity sha512-cPjLXj8d6anFPzFvOPxS3fvly3Shm5nTfl6g8X5smexixbuGUf7hfr21J5tX9JW+UPStp/5P5R8qrKL5IyVJ+A== integrity sha512-cPjLXj8d6anFPzFvOPxS3fvly3Shm5nTfl6g8X5smexixbuGUf7hfr21J5tX9JW+UPStp/5P5R8qrKL5IyVJ+A==
"@types/node@^16.7.1": "@types/node@^17.0.21":
version "16.11.25" version "17.0.21"
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.25.tgz#bb812b58bacbd060ce85921250d8b4ca553cd4a2" resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.21.tgz#864b987c0c68d07b4345845c3e63b75edd143644"
integrity sha512-NrTwfD7L1RTc2qrHQD4RTTy4p0CO2LatKBEKEds3CaVuhoM/+DJzmWZl5f+ikR8cm8F5mfJxK+9rQq07gRiSjQ== integrity sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==
"@types/prettier@^2.1.5": "@types/prettier@^2.1.5":
version "2.4.4" version "2.4.4"
@@ -3495,6 +3495,11 @@ eyes@^0.1.8:
resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0"
integrity sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A= integrity sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=
fast-copy@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-2.1.1.tgz#f5cbcf2df64215e59b8e43f0b2caabc19848083a"
integrity sha512-Qod3DdRgFZ8GUIM6ygeoZYpQ0QLW9cf/FS9KhhjlYggcSZXWAemAw8BOCO5LuYCrR3Uj3qXDVTUzOUwG8C7beQ==
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
version "3.1.3" version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"