Skip to content

Commit

Permalink
perf: add perf benchmark
Browse files Browse the repository at this point in the history
  • Loading branch information
raveclassic committed Feb 26, 2022
1 parent 1df4764 commit cb8d8f2
Show file tree
Hide file tree
Showing 23 changed files with 1,118 additions and 35 deletions.
18 changes: 18 additions & 0 deletions apps/benchmark/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}
15 changes: 15 additions & 0 deletions apps/benchmark/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module.exports = {
displayName: 'benchmark',
preset: '../../jest.preset.js',
globals: {
'ts-jest': {
tsconfig: '<rootDir>/tsconfig.spec.json',
},
},
testEnvironment: 'node',
transform: {
'^.+\\.[tj]s$': 'ts-jest',
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/apps/benchmark',
}
29 changes: 29 additions & 0 deletions apps/benchmark/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "@frp-ts/benchmark",
"version": "1.0.0-alpha.13",
"description": "Performance benchmark for @frp-ts project",
"author": "raveclassic",
"license": "MIT",
"type": "commonjs",
"repository": {
"type": "git",
"url": "git+https://github.com/raveclassic/frp-ts.git"
},
"bugs": {
"url": "https://github.com/raveclassic/frp-ts/issues"
},
"homepage": "https://github.com/raveclassic/frp-ts#readme",
"scripts": {
"run": "ts-node ./src/index.ts"
},
"private": true,
"dependencies": {
"@frp-ts/core": "file://../../dist/packages/core",
"@frp-ts/utils": "file://../../dist/packages/utils",
"cellx": "1.10.26",
"mol_wire_lib": "^1.0.56",
"@reatom/core": "2.0.17",
"tslib": "^2.3.1"
},
"devDependencies": {}
}
45 changes: 45 additions & 0 deletions apps/benchmark/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"root": "apps/benchmark",
"sourceRoot": "apps/benchmark/src",
"projectType": "application",
"targets": {
"build": {
"executor": "@nrwl/node:build",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/apps/benchmark",
"main": "apps/benchmark/src/index.ts",
"tsConfig": "apps/benchmark/tsconfig.app.json"
}
},
"oldserve": {
"executor": "@nrwl/node:execute",
"options": {
"buildTarget": "benchmark:build"
}
},
"serve": {
"executor": "@nrwl/workspace:run-commands",
"options": {
"cwd": "apps/benchmark",
"command": "ts-node ./src/index.ts"
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["apps/benchmark/**/*.ts"]
}
},
"test": {
"executor": "@nrwl/jest:jest",
"outputs": ["coverage/apps/benchmark"],
"options": {
"jestConfig": "apps/benchmark/jest.config.js",
"passWithNoTests": true
}
}
},
"tags": []
}
Empty file added apps/benchmark/src/app/.gitkeep
Empty file.
Empty file.
Empty file.
Empty file.
161 changes: 161 additions & 0 deletions apps/benchmark/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/**
* Adopted from https://github.com/artalar/reatom/blob/v2/packages/core/src/index.bench.test.ts
* All credits to @artalar
*/

import { buildFRPTS, measureFRPTSPush } from './utils/frp-ts-utils'
import { buildCellX, measureCellXPush } from './utils/cellx-utils'
import { buildReatom } from './utils/reatom-utils'
import { defaultStore } from '@reatom/core'
import { buildMolWireFiber, measureMolWireFiberPush } from './utils/mol-utils'
import { log, printLogs, validateResults } from './utils/test-utils'

function testBuild(iterations: number) {
let i = 0
const frptsLog: number[] = []
let frptsResult: unknown = undefined
const cellxLog: number[] = []
let cellxResult: unknown = undefined
const reatomLog: number[] = []
let reatomResult: unknown = undefined
const molWireFiberLog: number[] = []
let molWireFiberResult: unknown = undefined
while (i++ < iterations) {
const frptsStart = performance.now()
frptsResult = buildFRPTS()
frptsLog.push(performance.now() - frptsStart)

const cellxStart = performance.now()
cellxResult = buildCellX()
cellxLog.push(performance.now() - cellxStart)

const reatomStart = performance.now()
reatomResult = buildReatom()
reatomLog.push(performance.now() - reatomStart)

const molWireFiberStart = performance.now()
molWireFiberResult = buildMolWireFiber()
molWireFiberLog.push(performance.now() - molWireFiberStart)
}

console.log('\nBuild', iterations)
printLogs({
'@frp-ts/core': log(frptsLog),
cellx: log(cellxLog),
reatom: log(reatomLog),
$mol_wire_fiber: log(molWireFiberLog),
})
}

function testPull(iterations: number) {
let i = 0
const frptsLog: number[] = []
const [frptsInput, frptsOutput] = buildFRPTS()
let frptsResult = 0

const cellxLog: number[] = []
const [cellxInput, cellxOutput] = buildCellX()
let cellxResult = 0

const reatomLog: number[] = []
const [reatomInput, reatomOutput] = buildReatom()
let reatomResult = 0

const molWireFiberLog: number[] = []
const [molWireFiberInput, molWireFiberOutput] = buildMolWireFiber()
let molWireFiberResult = 0

while (i++ < iterations) {
const frptsStart = performance.now()
frptsInput.set(i)
frptsResult += frptsOutput.get()
frptsLog.push(performance.now() - frptsStart)

const cellxStart = performance.now()
cellxInput(i)
cellxResult += cellxOutput()
cellxLog.push(performance.now() - cellxStart)

const reatomStart = performance.now()
defaultStore.dispatch(reatomInput.entry(i))
reatomResult += reatomOutput.getState()
reatomLog.push(performance.now() - reatomStart)

const molWireFiberStart = performance.now()
molWireFiberInput.put(i)
molWireFiberResult += molWireFiberOutput.sync()
molWireFiberLog.push(performance.now() - molWireFiberStart)
}

console.log('\nPull', iterations)
validateResults(frptsResult, cellxResult, reatomResult, molWireFiberResult)
printLogs({
'@frp-ts/core': log(frptsLog),
cellx: log(cellxLog),
reatom: log(reatomLog),
$mol_wire_fiber: log(molWireFiberLog),
})
}

async function testPush(iterations: number) {
const frptsLog: number[] = []
const [frptsInput, frptsOutput] = buildFRPTS()
let frptsResult = 0

const cellxLog: number[] = []
const [cellxInput, cellxOutput] = buildCellX()
let cellxResult = 0

const molWireFiberLog: number[] = []
const [molWireFiberInput, molWireFiberOutput] = buildMolWireFiber()
let molWireFiberResult = 0

let i = 0
while (i++ < iterations) {
const [frptsValue, frptsTime] = await measureFRPTSPush(i, frptsInput, frptsOutput)
frptsResult += frptsValue
frptsLog.push(frptsTime)

const [cellxValue, cellxTime] = await measureCellXPush(i, cellxInput, cellxOutput)
cellxResult += cellxValue
cellxLog.push(cellxTime)

const [molWireFiberValue, molWireFiberTime] = await measureMolWireFiberPush(
i,
molWireFiberInput,
molWireFiberOutput,
)
molWireFiberResult += molWireFiberValue
molWireFiberLog.push(molWireFiberTime)
}

console.log('\nPush', iterations)
validateResults(frptsResult, cellxResult, molWireFiberResult)
printLogs({
'@frp-ts/core': log(frptsLog),
cellx: log(cellxLog),
$mol_wire_fiber: log(molWireFiberLog),
})
}

async function run() {
testBuild(100)
testBuild(1_000)
testBuild(10_000)

testPull(100)
testPull(1_000)
testPull(10_000)

await testPush(100)
await testPush(1_000)
await testPush(10_000)
}

void run()
.then(() => console.log('\nDone'))
.catch((e) => {
console.log('\nError')
console.error(e)
process.exit(1)
})
39 changes: 39 additions & 0 deletions apps/benchmark/src/utils/cellx-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { cellx, ICellx } from 'cellx'
import { PushMeasurement } from './test-utils'

export const buildCellX = (): [input: ICellx<number>, output: ICellx<number>] => {
const _0 = cellx(0)
const _10 = cellx(() => _0() + 1)
const _11 = cellx(() => _0() + 1)
const _20 = cellx(() => _10() + 1)
const _21 = cellx(() => _10() + _11())
const _22 = cellx(() => _11() + 1)
const _30 = cellx(() => _20() + 1)
const _31 = cellx(() => _20() + _21())
const _32 = cellx(() => _21() + _22())
const _33 = cellx(() => _22() + 1)
const _40 = cellx(() => _30() + _31())
const _41 = cellx(() => _31() + _32())
const _42 = cellx(() => _32() + _33())
const _50 = cellx(() => _40() + _41())
const _51 = cellx(() => _41() + _42())
const _60 = cellx(() => _50() + _51())
return [_0, _60]
}

export const measureCellXPush = (
iteration: number,
input: ICellx<number>,
output: ICellx<number>,
): Promise<PushMeasurement> =>
new Promise((resolve) => {
const listener = () => {
const value = output()
const time = performance.now() - start
subscription.unsubscribe(listener)
resolve([value, time])
}
const subscription = output.subscribe(listener)
const start = performance.now()
input(iteration)
})
40 changes: 40 additions & 0 deletions apps/benchmark/src/utils/frp-ts-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Atom, combine, newAtom, Property } from '@frp-ts/core'
import { PushMeasurement } from './test-utils'

export const buildFRPTS = (): [input: Atom<number>, output: Property<number>] => {
const _0 = newAtom(0)
const _10 = combine(_0, (v) => v + 1)
const _11 = combine(_0, (v) => v + 1)
const _20 = combine(_10, (v) => v + 1)
const _21 = combine(_10, _11, (a, b) => a + b)
const _22 = combine(_11, (v) => v + 1)
const _30 = combine(_20, (v) => v + 1)
const _31 = combine(_20, _21, (a, b) => a + b)
const _32 = combine(_21, _22, (a, b) => a + b)
const _33 = combine(_22, (v) => v + 1)
const _40 = combine(_30, _31, (a, b) => a + b)
const _41 = combine(_31, _32, (a, b) => a + b)
const _42 = combine(_32, _33, (a, b) => a + b)
const _50 = combine(_40, _41, (a, b) => a + b)
const _51 = combine(_41, _42, (a, b) => a + b)
const _60 = combine(_50, _51, (a, b) => a + b)
return [_0, _60]
}

export const measureFRPTSPush = (
iteration: number,
input: Atom<number>,
output: Property<number>,
): Promise<PushMeasurement> =>
new Promise((resolve) => {
const subscription = output.subscribe({
next: () => {
const value = output.get()
const time = performance.now() - start
subscription.unsubscribe()
resolve([value, time])
},
})
const start = performance.now()
input.set(iteration)
})
37 changes: 37 additions & 0 deletions apps/benchmark/src/utils/mol-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { $mol_wire_fiber } from 'mol_wire_lib'
import { PushMeasurement } from './test-utils'

export const buildMolWireFiber = () => {
const _0 = new $mol_wire_fiber('_0', (next: number = 0) => next)

const _10 = new $mol_wire_fiber('_10', () => _0.sync() + 1)
const _11 = new $mol_wire_fiber('_11', () => _0.sync() + 1)
const _20 = new $mol_wire_fiber('_20', () => _10.sync() + 1)
const _21 = new $mol_wire_fiber('_21', () => _10.sync() + _11.sync())
const _22 = new $mol_wire_fiber('_22', () => _11.sync() + 1)
const _30 = new $mol_wire_fiber('_30', () => _20.sync() + 1)
const _31 = new $mol_wire_fiber('_31', () => _20.sync() + _21.sync())
const _32 = new $mol_wire_fiber('_32', () => _21.sync() + _22.sync())
const _33 = new $mol_wire_fiber('_33', () => _22.sync() + 1)
const _40 = new $mol_wire_fiber('_40', () => _30.sync() + _31.sync())
const _41 = new $mol_wire_fiber('_41', () => _31.sync() + _32.sync())
const _42 = new $mol_wire_fiber('_42', () => _32.sync() + _33.sync())
const _50 = new $mol_wire_fiber('_50', () => _40.sync() + _41.sync())
const _51 = new $mol_wire_fiber('_51', () => _41.sync() + _42.sync())
const _60 = new $mol_wire_fiber('_60', () => _50.sync() + _51.sync())
return [_0, _60]
}

export const measureMolWireFiberPush = (
iteration: number,
input: $mol_wire_fiber<unknown, [], number>,
output: $mol_wire_fiber<unknown, [], number>,
): Promise<PushMeasurement> =>
new Promise((resolve) => {
const start = performance.now()
input.put(iteration)
output.async().then((value) => {
const time = performance.now() - start
resolve([value, time])
})
})
Loading

0 comments on commit cb8d8f2

Please sign in to comment.