Skip to content

Commit

Permalink
🧪 test(benchmark): Add benchmarking
Browse files Browse the repository at this point in the history
  • Loading branch information
Snowflyt committed Nov 11, 2024
1 parent 43cf012 commit 064d031
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 2 deletions.
51 changes: 51 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@
"module": "./index.js",
"types": "./index.d.ts",
"scripts": {
"bench": "vitest bench --run",
"bench:watch": "vitest bench",
"prebuild": "npm run clean",
"build": "tsc --emitDeclarationOnly -p tsconfig.build.json && sucrase src -d dist --transforms typescript && rimraf -g dist/*.{spec,proof}.js dist/types.{d.js,d.ts} && cpy src/**/*.{js,d.ts} dist && tsc-alias -p tsconfig.build.json && replace-in-file \"/^\\s*\\/\\/ eslint-disable-next-line .+$/mg\" \"\" dist/**/*.js --isRegex && replace-in-file \"/^\\s*\\/\\/ @ts-.+$/mg\" \"\" dist/**/*.js --isRegex && prettier --log-level=silent --print-width 80 --write dist/**/* --ignore-path !dist/**/* && cpy package.json dist && json -I -f dist/package.json -e \"delete this.private; delete this.scripts; delete this.devDependencies\" && cpy README.md dist && cpy screenshot.svg dist && cpy LICENSE dist",
"build": "tsc --emitDeclarationOnly -p tsconfig.build.json && sucrase src -d dist --transforms typescript && rimraf -g dist/*.{proof,spec,bench}.js dist/types.{d.js,d.ts} && cpy src/**/*.{js,d.ts} dist && tsc-alias -p tsconfig.build.json && replace-in-file \"/^\\s*\\/\\/ eslint-disable-next-line .+$/mg\" \"\" dist/**/*.js --isRegex && replace-in-file \"/^\\s*\\/\\/ @ts-.+$/mg\" \"\" dist/**/*.js --isRegex && prettier --log-level=silent --print-width 80 --write dist/**/* --ignore-path !dist/**/* && cpy package.json dist && json -I -f dist/package.json -e \"delete this.private; delete this.scripts; delete this.devDependencies\" && cpy README.md dist && cpy screenshot.svg dist && cpy LICENSE dist",
"clean": "rimraf dist",
"format": "prettier --no-error-on-unmatched-pattern --write **/*.{js,ts,json,md} *.{cjs,mjs,cts,mts}",
"lint": "eslint **/*.{js,ts} *.{cjs,mjs,cts,mts} --no-error-on-unmatched-pattern --report-unused-disable-directives-severity error --max-warnings 0",
Expand All @@ -50,6 +52,7 @@
"@vitest/coverage-v8": "^2.1.4",
"@vitest/ui": "^2.1.4",
"cpy-cli": "^5.0.0",
"effect": "^3.10.13",
"eslint": "^8.57.1",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.3",
Expand Down
64 changes: 64 additions & 0 deletions src/fib.bench.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* Benchmark for overhead of computationally expensive functions.
*
* Currently the effected version is around 100x (`fibPipe`) to 200x (`fibGen`) slower than the
* non-effected version.
*
* Such overhead should be acceptable for most use-cases, as real-world applications are unlikely to
* execute computationally expensive logic in an effected function.
*
* It is worth noting that tinyeffect’s version using generator syntax is around 20% faster than
* Effect’s version using `Effect.gen`, but the one using pipeline syntax is around 30%~120% slower
* than Effect’s version, which is quite surprising. A further investigation is needed to find out
* why Effect’s version is faster than tinyeffect’s version using pipeline syntax.
*/

import { Effect } from "effect";
import { bench, describe } from "vitest";

import { Effected, effected } from ".";

const fib = (n: number): number => {
if (n <= 1) return n;
return fib(n - 1) + fib(n - 2);
};

const fibGen = (n: number): Effected<never, number> =>
effected(function* () {
if (n <= 1) return n;
return (yield* fibGen(n - 1)) + (yield* fibGen(n - 2));
});

const fibPipe = (n: number): Effected<never, number> => {
if (n <= 1) return Effected.of(n);
return fibPipe(n - 1).map((a) => fibPipe(n - 2).map((b) => a + b));
};

const fibEGen = (n: number): Effect.Effect<number, never, never> =>
Effect.gen(function* () {
if (n <= 1) return n;
return (yield* fibEGen(n - 1)) + (yield* fibEGen(n - 2));
});

const fibEPipe = (n: number): Effect.Effect<number, never, never> => {
if (n <= 1) return Effect.succeed(n);
return fibEPipe(n - 1).pipe(
Effect.flatMap((a) => fibEPipe(n - 2).pipe(Effect.map((b) => a + b))),
);
};

describe("fib(20)", () => {
bench("fib(20)", () => void fib(20));
bench("fibGen(20)", () => void fibGen(20).runSync());
bench("fibPipe(20)", () => void fibPipe(20).runSync());
bench("fibEGen(20)", () => void Effect.runSync(fibEGen(20)));
bench("fibEPipe(20)", () => void Effect.runSync(fibEPipe(20)));
});

describe("fib(30)", () => {
bench("fib(30)", () => void fib(30));
bench("fibGen(30)", () => void fibGen(30).runSync());
bench("fibPipe(30)", () => void fibPipe(30).runSync());
bench("fibEGen(30)", () => void Effect.runSync(fibEGen(30)));
bench("fibEPipe(30)", () => void Effect.runSync(fibEPipe(30)));
});
2 changes: 1 addition & 1 deletion tsconfig.build.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"outDir": "dist"
},
"include": ["src"],
"exclude": ["src/**/*.spec.ts", "src/**/*.proof.ts"],
"exclude": ["src/**/*.proof.ts", "src/**/*.spec.ts", "src/**/*.bench.ts"],
"tsc-alias": {
"resolveFullPaths": true
}
Expand Down

0 comments on commit 064d031

Please sign in to comment.