From 9ca1223ec3ce9562e200220486fd1fd6c787a5ee Mon Sep 17 00:00:00 2001 From: palumbon Date: Fri, 27 Dec 2024 16:59:57 -0300 Subject: [PATCH 01/16] Running benchmarks --- package.json | 1 + test/benchmarks.test.ts | 48 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 test/benchmarks.test.ts diff --git a/package.json b/package.json index 6b956bec..6ed6acb7 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "test:wtest": "mocha --delay -t 10000 -r ts-node/register/transpile-only test/wtest.ts", "test:printer": "mocha --parallel -r ts-node/register/transpile-only test/printer.test.ts", "test:parser": "mocha -r ts-node/register/transpile-only test/parser.test.ts", + "test:benchmarks": "mocha -r ts-node/register/transpile-only test/benchmarks.test.ts", "lint:fix": "eslint . --fix", "validate:wollokVersion": "ts-node scripts/validateWollokVersion.ts", "prepublishOnly": "npm run validate:wollokVersion && npm run build && npm test", diff --git a/test/benchmarks.test.ts b/test/benchmarks.test.ts new file mode 100644 index 00000000..cab15ca9 --- /dev/null +++ b/test/benchmarks.test.ts @@ -0,0 +1,48 @@ +import { should } from 'chai' +import { resolve } from 'path' +import { Environment, Execution, get, Natives, PROGRAM_FILE_EXTENSION, RuntimeObject } from '../src' +import { interpret, interprete, Interpreter } from '../src/interpreter/interpreter' +import natives from '../src/wre/wre.natives' +import { buildEnvironment } from './assertions' + +should() + +describe('Wollok Game', () => { + + describe('flushEvents', () => { + + let environment: Environment + let interpreter: Interpreter + + beforeEach(async() => { + environment = await buildEnvironment(`**/*.${PROGRAM_FILE_EXTENSION}`, resolve('language', 'benchmarks')) + interpreter = interpret(environment, natives) + }) + + function benchmark(fqn: string, expectedTime = 0) { + it(fqn, () => { + interpreter.run(`games.${fqn}`) + const game = interpreter.object('wollok.game.game') + const message = 'flushEvents' + const ms = interpreter.reify(1) + + const startTime = performance.now() + interpreter.send(message, game, ms) + const endTime = performance.now() + const elapsedTime = endTime - startTime + + console.log(`${fqn} - ${message} - ${elapsedTime}`) + elapsedTime.should.be.closeTo(expectedTime, 2) + }) + } + + benchmark('empty', 5) + benchmark('visuals_1', 5) + benchmark('visuals_100', 1) // lookup cache + benchmark('ticks_1', 5.5) + benchmark('ticks_100', 61) + benchmark('onCollide_1', 1) // lookup cache + benchmark('onCollide_100', 52) + + }) +}) \ No newline at end of file From 1cee6c31ad4801880c1fb08bacb2f1ebc85d08ee Mon Sep 17 00:00:00 2001 From: palumbon Date: Fri, 27 Dec 2024 17:07:45 -0300 Subject: [PATCH 02/16] Improving game natives for performance --- src/wre/game.ts | 95 +++++++++++++++++++++++------------------ test/benchmarks.test.ts | 4 +- 2 files changed, 55 insertions(+), 44 deletions(-) diff --git a/src/wre/game.ts b/src/wre/game.ts index 8a4c3c9d..3e300bd8 100644 --- a/src/wre/game.ts +++ b/src/wre/game.ts @@ -1,7 +1,45 @@ import { GAME_MODULE } from '../constants' -import { assertIsNumber, assertIsNotNull, Execution, Natives, RuntimeObject, RuntimeValue } from '../interpreter/runtimeModel' +import { assertIsNotNull, assertIsNumber, Execution, NativeFunction, Natives, RuntimeObject, RuntimeValue } from '../interpreter/runtimeModel' const { round } = Math + + +/** + * Avoid to invoke getters method from properties by accessing directly to the variable + */ +const getter = (message: string): NativeFunction => function* (obj: RuntimeObject): Execution { + const method = obj.module.lookupMethod(message, 0)! + return method.isSynthetic ? obj.get(message)! : yield* this.invoke(method, obj) +} + +const getPosition = getter('position') +const getX = getter('x') +const getY = getter('y') + +const getObjectsIn: NativeFunction = function* (position: RuntimeObject, ...visuals: RuntimeObject[]): Execution { + const result: RuntimeObject[] = [] + + const x = (yield* getX.call(this, position))?.innerNumber + const y = (yield* getY.call(this, position))?.innerNumber + + if (x == undefined || y == undefined) throw new RangeError('Position without coordinates') + + const roundedX = round(x) + const roundedY = round(y) + for (const visual of visuals) { + const otherPosition = (yield* getPosition.call(this, visual))! + const otherX = (yield* getX.call(this, otherPosition))?.innerNumber + const otherY = (yield* getY.call(this, otherPosition))?.innerNumber + + if (otherX == undefined || otherY == undefined) continue // Do NOT throw exception + + if (roundedX == round(otherX) && roundedY == round(otherY)) + result.push(visual) + } + + return yield* this.list(...result) +} + const game: Natives = { game: { *addVisual(self: RuntimeObject, positionable: RuntimeObject): Execution { @@ -30,33 +68,7 @@ const game: Natives = { *getObjectsIn(self: RuntimeObject, position: RuntimeObject): Execution { const visuals = self.get('visuals')! - const result: RuntimeObject[] = [] - const x = position.get('x')?.innerNumber - const y = position.get('y')?.innerNumber - - - if(x != undefined && y != undefined) { - const roundedX = round(x) - const roundedY = round(y) - for(const visual of visuals.innerCollection!) { - - // Every visual understand position(), it is checked in addVisual(visual). - // Avoid to invoke method position() for optimisation reasons. - // -> If method isSynthetic then it is a getter, we can access to the field directly - const method = visual.module.lookupMethod('position', 0)! - const otherPosition = method.isSynthetic ? visual.get('position') :yield* this.invoke(method, visual) - - const otherX = otherPosition?.get('x')?.innerNumber - const otherY = otherPosition?.get('y')?.innerNumber - - if(otherX == undefined || otherY == undefined) continue - - if(roundedX == round(otherX) && roundedY == round(otherY)) - result.push(visual) - } - } - - return yield* this.list(...result) + return (yield* getObjectsIn.call(this, position, ...visuals.innerCollection!))! }, *say(self: RuntimeObject, visual: RuntimeObject, message: RuntimeObject): Execution { @@ -70,27 +82,26 @@ const game: Natives = { *colliders(self: RuntimeObject, visual: RuntimeObject): Execution { assertIsNotNull(visual, 'colliders', 'visual') - - const position = (yield* this.send('position', visual))! - const visualsAtPosition: RuntimeObject = (yield* this.send('getObjectsIn', self, position))! - - yield* this.send('remove', visualsAtPosition, visual) - - return visualsAtPosition + + const visuals = self.get('visuals')! + const otherVisuals = visuals.innerCollection!.filter(obj => obj != visual) + const position = (yield* getPosition.call(this, visual))! + + return (yield* getObjectsIn.call(this, position, ...otherVisuals))! }, *title(self: RuntimeObject, title?: RuntimeObject): Execution { - if(!title) return self.get('title') + if (!title) return self.get('title') self.set('title', title) }, *width(self: RuntimeObject, width?: RuntimeObject): Execution { - if(!width) return self.get('width') + if (!width) return self.get('width') self.set('width', width) }, *height(self: RuntimeObject, height?: RuntimeObject): Execution { - if(!height) return self.get('height') + if (!height) return self.get('height') self.set('height', height) }, @@ -135,9 +146,9 @@ const game: Natives = { const game = this.object(GAME_MODULE)! const sounds = game.get('sounds') - if(sounds) yield* this.send('remove', sounds, self) + if (sounds) yield* this.send('remove', sounds, self) - self.set('status', yield * this.reify('stopped')) + self.set('status', yield* this.reify('stopped')) }, *pause(self: RuntimeObject): Execution { @@ -161,7 +172,7 @@ const game: Natives = { }, *volume(self: RuntimeObject, newVolume?: RuntimeObject): Execution { - if(!newVolume) return self.get('volume') + if (!newVolume) return self.get('volume') const volume: RuntimeObject = newVolume assertIsNumber(volume, 'volume', 'newVolume', false) @@ -172,7 +183,7 @@ const game: Natives = { }, *shouldLoop(self: RuntimeObject, looping?: RuntimeObject): Execution { - if(!looping) return self.get('loop') + if (!looping) return self.get('loop') self.set('loop', looping) }, diff --git a/test/benchmarks.test.ts b/test/benchmarks.test.ts index cab15ca9..0880d42d 100644 --- a/test/benchmarks.test.ts +++ b/test/benchmarks.test.ts @@ -1,7 +1,7 @@ import { should } from 'chai' import { resolve } from 'path' -import { Environment, Execution, get, Natives, PROGRAM_FILE_EXTENSION, RuntimeObject } from '../src' -import { interpret, interprete, Interpreter } from '../src/interpreter/interpreter' +import { Environment, PROGRAM_FILE_EXTENSION } from '../src' +import { interpret, Interpreter } from '../src/interpreter/interpreter' import natives from '../src/wre/wre.natives' import { buildEnvironment } from './assertions' From a5ed7b85cc31843a0c2af9d8404bd0f46745e9f1 Mon Sep 17 00:00:00 2001 From: palumbon Date: Fri, 3 Jan 2025 17:55:03 -0300 Subject: [PATCH 03/16] Update benchmark times --- test/benchmarks.test.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/test/benchmarks.test.ts b/test/benchmarks.test.ts index 0880d42d..95eda472 100644 --- a/test/benchmarks.test.ts +++ b/test/benchmarks.test.ts @@ -31,17 +31,18 @@ describe('Wollok Game', () => { const endTime = performance.now() const elapsedTime = endTime - startTime + const deltaError = 0.3 * expectedTime console.log(`${fqn} - ${message} - ${elapsedTime}`) - elapsedTime.should.be.closeTo(expectedTime, 2) + elapsedTime.should.be.closeTo(expectedTime, deltaError) }) } - benchmark('empty', 5) - benchmark('visuals_1', 5) - benchmark('visuals_100', 1) // lookup cache - benchmark('ticks_1', 5.5) + benchmark('empty', 2.5) + benchmark('visuals_1', 2.5) + benchmark('visuals_100', 0.6) // lookup cache + benchmark('ticks_1', 4) benchmark('ticks_100', 61) - benchmark('onCollide_1', 1) // lookup cache + benchmark('onCollide_1', 1.2) // lookup cache benchmark('onCollide_100', 52) }) From 41360de08e23427cf4ba5775dc6f8cb02ab67179 Mon Sep 17 00:00:00 2001 From: palumbon Date: Fri, 3 Jan 2025 20:25:51 -0300 Subject: [PATCH 04/16] Compile property methods as natives --- src/helpers.ts | 21 +++++++++++++++++++-- src/interpreter/runtimeModel.ts | 14 +++++++++----- src/model.ts | 6 +++++- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/helpers.ts b/src/helpers.ts index a185e4b6..b64f22ee 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -1,7 +1,7 @@ import { BOOLEAN_MODULE, CLOSURE_EVALUATE_METHOD, CLOSURE_MODULE, CLOSURE_TO_STRING_METHOD, INITIALIZE_METHOD, KEYWORDS, NUMBER_MODULE, OBJECT_MODULE, STRING_MODULE, VOID_WKO, WOLLOK_BASE_PACKAGE } from './constants' import { getPotentiallyUninitializedLazy } from './decorators' import { count, is, isEmpty, last, List, match, notEmpty, otherwise, valueAsListOrEmpty, when, excludeNullish } from './extensions' -import { RuntimeObject, RuntimeValue } from './interpreter/runtimeModel' +import { Execution, NativeFunction, RuntimeObject, RuntimeValue } from './interpreter/runtimeModel' import { Assignment, Body, Class, CodeContainer, Describe, Entity, Environment, Expression, Field, If, Import, Literal, LiteralValue, Method, Module, Name, NamedArgument, New, Node, Package, Parameter, ParameterizedType, Problem, Program, Reference, Referenciable, Return, Self, Send, Sentence, Singleton, Super, Test, Throw, Try, Variable } from './model' export const LIBRARY_PACKAGES = ['wollok.lang', 'wollok.lib', 'wollok.game', 'wollok.vm', 'wollok.mirror'] @@ -477,4 +477,21 @@ export const showParameter = (obj: RuntimeObject): string => `"${obj.getShortRepresentation().trim() || obj.module.fullyQualifiedName}"` export const getMethodContainer = (node: Node): Method | Program | Test | undefined => - last(node.ancestors.filter(parent => parent.is(Method) || parent.is(Program) || parent.is(Test))) as unknown as Method | Program | Test \ No newline at end of file + last(node.ancestors.filter(parent => parent.is(Method) || parent.is(Program) || parent.is(Test))) as unknown as Method | Program | Test + +/** + * NATIVES + */ +export const compilePropertyMethod = (method: Method): NativeFunction => { + const message = method.name + return method.parameters.length == 0 + ? compileGetter(message) + : compileSetter(message) +} + +export const compileGetter = (message: string): NativeFunction => function* (self: RuntimeObject): Execution { + return self.get(message) +} +export const compileSetter = (message: string): NativeFunction => function* (self: RuntimeObject, value: RuntimeObject): Execution { + self.set(message, value) +} diff --git a/src/interpreter/runtimeModel.ts b/src/interpreter/runtimeModel.ts index 48f1f3df..c0549309 100644 --- a/src/interpreter/runtimeModel.ts +++ b/src/interpreter/runtimeModel.ts @@ -1,7 +1,7 @@ import { v4 as uuid } from 'uuid' import { BOOLEAN_MODULE, CLOSURE_EVALUATE_METHOD, CLOSURE_MODULE, DATE_MODULE, DICTIONARY_MODULE, EXCEPTION_MODULE, INITIALIZE_METHOD, KEYWORDS, LIST_MODULE, NUMBER_MODULE, OBJECT_MODULE, PAIR_MODULE, RANGE_MODULE, SET_MODULE, STRING_MODULE, TO_STRING_METHOD, VOID_WKO, WOLLOK_BASE_PACKAGE, WOLLOK_EXTRA_STACK_TRACE_HEADER } from '../constants' import { get, is, last, List, match, otherwise, raise, when } from '../extensions' -import { assertNotVoid, getExpressionFor, getMethodContainer, getUninitializedAttributesForInstantiation, isNamedSingleton, isVoid, loopInAssignment, showParameter, superMethodDefinition, targetName } from '../helpers' +import { assertNotVoid, compilePropertyMethod, getExpressionFor, getMethodContainer, getUninitializedAttributesForInstantiation, isNamedSingleton, isVoid, loopInAssignment, showParameter, superMethodDefinition, targetName } from '../helpers' import { Assignment, Body, Catch, Class, Describe, Entity, Environment, Expression, Field, Id, If, Literal, LiteralValue, Method, Module, Name, New, Node, Program, Reference, Return, Self, Send, Singleton, Super, Test, Throw, Try, Variable } from '../model' import { Interpreter } from './interpreter' @@ -317,11 +317,15 @@ export class Evaluation { // Set natives environment.forEach(node => { - if (node.is(Method) && node.isNative()) - evaluation.natives.set(node, get(natives, `${node.parent.fullyQualifiedName}.${node.name}`)!) + if (node.is(Method)) + if (node.isNative()) + evaluation.natives.set(node, get(natives, `${node.parent.fullyQualifiedName}.${node.name}`)!) + else if (node.isSynthetic && node.name !== CLOSURE_EVALUATE_METHOD) { + evaluation.natives.set(node, compilePropertyMethod(node)) + node.compiled = true + } }) - // Instanciate globals const globalSingletons = environment.descendants.filter((node: Node): node is Singleton => isNamedSingleton(node)) for (const module of globalSingletons) @@ -459,7 +463,7 @@ export class Evaluation { protected *execMethod(node: Method): Execution { yield node - if (node.isNative()) { + if (node.hasNativeImplementation) { const native = this.natives.get(node) if (!native) throw new Error(`Missing native for ${node.parent.fullyQualifiedName}.${node.name}`) diff --git a/src/model.ts b/src/model.ts index 3b591403..f1cb621e 100644 --- a/src/model.ts +++ b/src/model.ts @@ -659,6 +659,8 @@ export class Method extends Node { override parent!: Module + compiled: boolean = false + constructor({ isOverride = false, parameters = [], ...payload }: Payload) { super({ isOverride, parameters, ...payload }) } @@ -672,8 +674,10 @@ export class Method extends Node { } isAbstract(): this is { body: undefined } { return !this.body } - isNative(): this is { body?: Body } { return this.body === KEYWORDS.NATIVE } isConcrete(): this is { body: Body } { return !this.isAbstract() && !this.isNative() } + isNative(): this is { body?: Body } { return this.body === KEYWORDS.NATIVE } + + get hasNativeImplementation(): boolean { return this.isNative() || this.compiled } @cached get hasVarArgs(): boolean { return !!last(this.parameters)?.isVarArg } From a1c874e47df0fa79b91af4cd084d58fe7ab8362f Mon Sep 17 00:00:00 2001 From: palumbon Date: Fri, 3 Jan 2025 20:28:03 -0300 Subject: [PATCH 05/16] Improve benchmark tests --- package.json | 2 +- test/benchmarks.test.ts | 75 ++++++++++++++++++++++++----------------- 2 files changed, 45 insertions(+), 32 deletions(-) diff --git a/package.json b/package.json index 6ed6acb7..b63caefd 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "test:wtest": "mocha --delay -t 10000 -r ts-node/register/transpile-only test/wtest.ts", "test:printer": "mocha --parallel -r ts-node/register/transpile-only test/printer.test.ts", "test:parser": "mocha -r ts-node/register/transpile-only test/parser.test.ts", - "test:benchmarks": "mocha -r ts-node/register/transpile-only test/benchmarks.test.ts", + "test:benchmarks": "mocha -t 50000 -r ts-node/register/transpile-only test/benchmarks.test.ts", "lint:fix": "eslint . --fix", "validate:wollokVersion": "ts-node scripts/validateWollokVersion.ts", "prepublishOnly": "npm run validate:wollokVersion && npm run build && npm test", diff --git a/test/benchmarks.test.ts b/test/benchmarks.test.ts index 95eda472..cd402c1e 100644 --- a/test/benchmarks.test.ts +++ b/test/benchmarks.test.ts @@ -1,7 +1,8 @@ import { should } from 'chai' import { resolve } from 'path' -import { Environment, PROGRAM_FILE_EXTENSION } from '../src' -import { interpret, Interpreter } from '../src/interpreter/interpreter' +import { restore, stub } from 'sinon' +import { PROGRAM_FILE_EXTENSION } from '../src' +import { interpret } from '../src/interpreter/interpreter' import natives from '../src/wre/wre.natives' import { buildEnvironment } from './assertions' @@ -11,39 +12,51 @@ describe('Wollok Game', () => { describe('flushEvents', () => { - let environment: Environment - let interpreter: Interpreter - - beforeEach(async() => { - environment = await buildEnvironment(`**/*.${PROGRAM_FILE_EXTENSION}`, resolve('language', 'benchmarks')) - interpreter = interpret(environment, natives) - }) - function benchmark(fqn: string, expectedTime = 0) { - it(fqn, () => { - interpreter.run(`games.${fqn}`) - const game = interpreter.object('wollok.game.game') + it(fqn, async () => { + stub(console) + const iterations = 30 + + const program = `games.${fqn}` const message = 'flushEvents' - const ms = interpreter.reify(1) - - const startTime = performance.now() - interpreter.send(message, game, ms) - const endTime = performance.now() - const elapsedTime = endTime - startTime - - const deltaError = 0.3 * expectedTime - console.log(`${fqn} - ${message} - ${elapsedTime}`) - elapsedTime.should.be.closeTo(expectedTime, deltaError) + + let totalTime = 0 + for (let index = 0; index < iterations; index++) + totalTime += await measure(program, message) + + + const averageTime = totalTime / iterations + const deltaError = expectedTime * 0.1 // 10 % + restore() + + console.log(`${fqn} - ${message} - ${averageTime} ms (${iterations} iterations)`) + averageTime.should.be.closeTo(expectedTime, deltaError) }) } - benchmark('empty', 2.5) - benchmark('visuals_1', 2.5) - benchmark('visuals_100', 0.6) // lookup cache - benchmark('ticks_1', 4) - benchmark('ticks_100', 61) - benchmark('onCollide_1', 1.2) // lookup cache - benchmark('onCollide_100', 52) + benchmark('empty', 0.58) + benchmark('visuals_1', 0.4) + benchmark('visuals_100', 0.3) + benchmark('ticks_1', 0.8) + benchmark('ticks_100', 44) + benchmark('onCollide_1', 0.8) + benchmark('onCollide_100', 44) }) -}) \ No newline at end of file +}) + +async function measure(programFQN: string, message: string): Promise { + const environment = await buildEnvironment(`**/*.${PROGRAM_FILE_EXTENSION}`, resolve('language', 'benchmarks')) + const interpreter = interpret(environment, natives) + + interpreter.run(programFQN) + const game = interpreter.object('wollok.game.game') + + interpreter.send(message, game, interpreter.reify(0)) // Fill caches + const startTime = performance.now() + interpreter.send(message, game, interpreter.reify(1)) + const endTime = performance.now() + + const elapsedTime = endTime - startTime + return elapsedTime +} \ No newline at end of file From 5037bb59e35dd0b3903a58883ee491a63b438ab3 Mon Sep 17 00:00:00 2001 From: palumbon Date: Sun, 5 Jan 2025 19:25:59 -0300 Subject: [PATCH 06/16] Aviod running benchmarks on test suites --- package.json | 4 ++-- test/{benchmarks.test.ts => benchmarks.ts} | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename test/{benchmarks.test.ts => benchmarks.ts} (95%) diff --git a/package.json b/package.json index b63caefd..ae9d6c03 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "prepare": "ts-node scripts/fetchLanguage.ts && npm run buildWRE && npm run copy:translations", "copy:translations": "cp ./language/src/resources/validationMessages/*.json ./src/validator", "diagnostic": "tsc --noEmit --diagnostics --extendedDiagnostics", - "test": "npm run test:lint && npm run test:unit && npm run test:sanity && npm run test:examples && npm run test:validations && npm run test:typeSystem && npm run test:printer", + "test": "npm run test:lint && npm run test:unit && npm run test:sanity && npm run test:examples", "test:lint": "eslint .", "test:coverage": "nyc --reporter=lcov npm run test", "test:unit": "mocha --parallel -r ts-node/register/transpile-only test/**/*.test.ts", @@ -33,7 +33,7 @@ "test:wtest": "mocha --delay -t 10000 -r ts-node/register/transpile-only test/wtest.ts", "test:printer": "mocha --parallel -r ts-node/register/transpile-only test/printer.test.ts", "test:parser": "mocha -r ts-node/register/transpile-only test/parser.test.ts", - "test:benchmarks": "mocha -t 50000 -r ts-node/register/transpile-only test/benchmarks.test.ts", + "test:benchmarks": "mocha -t 50000 -r ts-node/register/transpile-only test/benchmarks.ts", "lint:fix": "eslint . --fix", "validate:wollokVersion": "ts-node scripts/validateWollokVersion.ts", "prepublishOnly": "npm run validate:wollokVersion && npm run build && npm test", diff --git a/test/benchmarks.test.ts b/test/benchmarks.ts similarity index 95% rename from test/benchmarks.test.ts rename to test/benchmarks.ts index cd402c1e..9eaa483f 100644 --- a/test/benchmarks.test.ts +++ b/test/benchmarks.ts @@ -29,7 +29,7 @@ describe('Wollok Game', () => { const deltaError = expectedTime * 0.1 // 10 % restore() - console.log(`${fqn} - ${message} - ${averageTime} ms (${iterations} iterations)`) + console.info(`${fqn} - ${message} - ${averageTime} ms (${iterations} iterations)`) averageTime.should.be.closeTo(expectedTime, deltaError) }) } @@ -51,7 +51,7 @@ async function measure(programFQN: string, message: string): Promise { interpreter.run(programFQN) const game = interpreter.object('wollok.game.game') - + interpreter.send(message, game, interpreter.reify(0)) // Fill caches const startTime = performance.now() interpreter.send(message, game, interpreter.reify(1)) From a029e3d73758deddfd5b4be98d84a7a2c8270fff Mon Sep 17 00:00:00 2001 From: palumbon Date: Sun, 5 Jan 2025 19:26:08 -0300 Subject: [PATCH 07/16] Fix lint --- src/helpers.ts | 2 +- src/interpreter/runtimeModel.ts | 4 ++-- src/model.ts | 2 +- src/wre/game.ts | 5 ++--- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/helpers.ts b/src/helpers.ts index b64f22ee..e6e3a442 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -494,4 +494,4 @@ export const compileGetter = (message: string): NativeFunction => function* (sel } export const compileSetter = (message: string): NativeFunction => function* (self: RuntimeObject, value: RuntimeObject): Execution { self.set(message, value) -} +} \ No newline at end of file diff --git a/src/interpreter/runtimeModel.ts b/src/interpreter/runtimeModel.ts index c0549309..6e5a9fa5 100644 --- a/src/interpreter/runtimeModel.ts +++ b/src/interpreter/runtimeModel.ts @@ -320,10 +320,10 @@ export class Evaluation { if (node.is(Method)) if (node.isNative()) evaluation.natives.set(node, get(natives, `${node.parent.fullyQualifiedName}.${node.name}`)!) - else if (node.isSynthetic && node.name !== CLOSURE_EVALUATE_METHOD) { + else if (node.isSynthetic && node.parent.lookupField(node.name)) { evaluation.natives.set(node, compilePropertyMethod(node)) node.compiled = true - } + } }) // Instanciate globals diff --git a/src/model.ts b/src/model.ts index f1cb621e..c35e4f31 100644 --- a/src/model.ts +++ b/src/model.ts @@ -659,7 +659,7 @@ export class Method extends Node { override parent!: Module - compiled: boolean = false + compiled = false constructor({ isOverride = false, parameters = [], ...payload }: Payload) { super({ isOverride, parameters, ...payload }) diff --git a/src/wre/game.ts b/src/wre/game.ts index 3e300bd8..47877459 100644 --- a/src/wre/game.ts +++ b/src/wre/game.ts @@ -3,7 +3,6 @@ import { assertIsNotNull, assertIsNumber, Execution, NativeFunction, Natives, Ru const { round } = Math - /** * Avoid to invoke getters method from properties by accessing directly to the variable */ @@ -82,11 +81,11 @@ const game: Natives = { *colliders(self: RuntimeObject, visual: RuntimeObject): Execution { assertIsNotNull(visual, 'colliders', 'visual') - + const visuals = self.get('visuals')! const otherVisuals = visuals.innerCollection!.filter(obj => obj != visual) const position = (yield* getPosition.call(this, visual))! - + return (yield* getObjectsIn.call(this, position, ...otherVisuals))! }, From 9b264bad6976091dc7562338bd6605aca8e68ebc Mon Sep 17 00:00:00 2001 From: palumbon Date: Sun, 5 Jan 2025 21:14:30 -0300 Subject: [PATCH 08/16] Improve benchmarks log --- .eslintrc | 3 ++- test/benchmarks.ts | 14 +++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.eslintrc b/.eslintrc index 2535c092..127578da 100644 --- a/.eslintrc +++ b/.eslintrc @@ -113,7 +113,8 @@ "time", "timeEnd", "group", - "groupEnd" + "groupEnd", + "table" ] } ], diff --git a/test/benchmarks.ts b/test/benchmarks.ts index 9eaa483f..adc64d6f 100644 --- a/test/benchmarks.ts +++ b/test/benchmarks.ts @@ -9,6 +9,9 @@ import { buildEnvironment } from './assertions' should() describe('Wollok Game', () => { + const results: any[] = [] + + after(() => console.table(results)) describe('flushEvents', () => { @@ -25,16 +28,17 @@ describe('Wollok Game', () => { totalTime += await measure(program, message) - const averageTime = totalTime / iterations - const deltaError = expectedTime * 0.1 // 10 % + const time = totalTime / iterations + const deltaError = Math.max(0.1, expectedTime * 0.1) // 0.1 or 10 % restore() - console.info(`${fqn} - ${message} - ${averageTime} ms (${iterations} iterations)`) - averageTime.should.be.closeTo(expectedTime, deltaError) + // console.info(`${message} - ${fqn} - ${time} ms (${iterations} iterations)`) + results.push({ message, fqn, time, iterations }) + time.should.be.closeTo(expectedTime, deltaError) }) } - benchmark('empty', 0.58) + benchmark('empty', 0.55) benchmark('visuals_1', 0.4) benchmark('visuals_100', 0.3) benchmark('ticks_1', 0.8) From f60e38c1315ec9ee64d49083221c5e98984503ff Mon Sep 17 00:00:00 2001 From: palumbon Date: Sun, 5 Jan 2025 21:38:41 -0300 Subject: [PATCH 09/16] Method.fromProperty() --- src/interpreter/runtimeModel.ts | 2 +- src/model.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/interpreter/runtimeModel.ts b/src/interpreter/runtimeModel.ts index 6e5a9fa5..b370f381 100644 --- a/src/interpreter/runtimeModel.ts +++ b/src/interpreter/runtimeModel.ts @@ -320,7 +320,7 @@ export class Evaluation { if (node.is(Method)) if (node.isNative()) evaluation.natives.set(node, get(natives, `${node.parent.fullyQualifiedName}.${node.name}`)!) - else if (node.isSynthetic && node.parent.lookupField(node.name)) { + else if (node.fromProperty()) { evaluation.natives.set(node, compilePropertyMethod(node)) node.compiled = true } diff --git a/src/model.ts b/src/model.ts index c35e4f31..77fe92b3 100644 --- a/src/model.ts +++ b/src/model.ts @@ -677,6 +677,8 @@ export class Method extends Node { isConcrete(): this is { body: Body } { return !this.isAbstract() && !this.isNative() } isNative(): this is { body?: Body } { return this.body === KEYWORDS.NATIVE } + fromProperty(): boolean { return this.isSynthetic && !!this.parent.lookupField(this.name) } + get hasNativeImplementation(): boolean { return this.isNative() || this.compiled } @cached From dd12fe93dba0160fa41ac7709440a446cb0dd42a Mon Sep 17 00:00:00 2001 From: palumbon Date: Mon, 6 Jan 2025 02:48:17 -0300 Subject: [PATCH 10/16] Hi benchmarks gh action --- .github/workflows/benchmarks.yml | 41 ++++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/benchmarks.yml diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml new file mode 100644 index 00000000..8eafcb93 --- /dev/null +++ b/.github/workflows/benchmarks.yml @@ -0,0 +1,41 @@ +name: Run Benchmarks + +on: + issue_comment: + types: + - created + +jobs: + run-benchmarks: + if: ${{ contains(github.event.comment.body, '[Run benchmarks]') && github.event.issue.pull_request }} + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Read .nvmrc + run: echo "##[set-output name=NVMRC;]$(cat .nvmrc)" + id: nvm + - name: Use Node.js (.nvmrc) + uses: actions/setup-node@v3 + with: + node-version: "${{ steps.nvm.outputs.NVMRC }}" + + - name: Install dependencies + run: npm install + + - name: Run benchmarks + id: benchmarks + run: npm run test:benchmarks + + - name: Post results to comment + uses: peter-evans/commit-comment@v3 + with: + repository: ${{ github.repository }} + comment-id: ${{ github.event.comment.id }} + body: | + ## Benchmark Results + ``` + ${{ steps.benchmarks.outputs.stdout }} + ``` diff --git a/package.json b/package.json index ae9d6c03..617c5ceb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wollok-ts", "version": "4.1.10", - "wollokVersion": ":master", + "wollokVersion": ":optimization-wollok-game", "description": "TypeScript based Wollok language implementation", "repository": "https://github.com/uqbar-project/wollok-ts", "license": "MIT", From e916496506b270da033148cc1e04e8267f53e469 Mon Sep 17 00:00:00 2001 From: palumbon Date: Mon, 6 Jan 2025 03:50:23 -0300 Subject: [PATCH 11/16] Testing benchmark workflow --- .github/workflows/benchmarks.yml | 40 ++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml index 8eafcb93..d35dc964 100644 --- a/.github/workflows/benchmarks.yml +++ b/.github/workflows/benchmarks.yml @@ -11,23 +11,23 @@ jobs: runs-on: ubuntu-latest steps: - - name: Checkout repository - uses: actions/checkout@v3 + # - name: Checkout repository + # uses: actions/checkout@v3 - - name: Read .nvmrc - run: echo "##[set-output name=NVMRC;]$(cat .nvmrc)" - id: nvm - - name: Use Node.js (.nvmrc) - uses: actions/setup-node@v3 - with: - node-version: "${{ steps.nvm.outputs.NVMRC }}" + # - name: Read .nvmrc + # run: echo "##[set-output name=NVMRC;]$(cat .nvmrc)" + # id: nvm + # - name: Use Node.js (.nvmrc) + # uses: actions/setup-node@v3 + # with: + # node-version: "${{ steps.nvm.outputs.NVMRC }}" - - name: Install dependencies - run: npm install + # - name: Install dependencies + # run: npm install - - name: Run benchmarks - id: benchmarks - run: npm run test:benchmarks + # - name: Run benchmarks + # id: benchmarks + # run: npm run test:benchmarks - name: Post results to comment uses: peter-evans/commit-comment@v3 @@ -37,5 +37,15 @@ jobs: body: | ## Benchmark Results ``` - ${{ steps.benchmarks.outputs.stdout }} + ┌─────────┬───────────────┬─────────────────┬─────────────────────┬────────────┐ + │ (index) │ message │ fqn │ time │ iterations │ + ├─────────┼───────────────┼─────────────────┼─────────────────────┼────────────┤ + │ 0 │ 'flushEvents' │ 'empty' │ 1.0739654541015624 │ 30 │ + │ 1 │ 'flushEvents' │ 'visuals_1' │ 0.48952223459879557 │ 30 │ + │ 2 │ 'flushEvents' │ 'visuals_100' │ 0.2899084726969401 │ 30 │ + │ 3 │ 'flushEvents' │ 'ticks_1' │ 0.8966011683146159 │ 30 │ + │ 4 │ 'flushEvents' │ 'ticks_100' │ 49.76229190826416 │ 30 │ + │ 5 │ 'flushEvents' │ 'onCollide_1' │ 1.091204325358073 │ 30 │ + │ 6 │ 'flushEvents' │ 'onCollide_100' │ 48.2887056350708 │ 30 │ + └─────────┴───────────────┴─────────────────┴─────────────────────┴────────────┘ ``` From db4e5ed119b8741cccc7ab5b2a76d995a7877985 Mon Sep 17 00:00:00 2001 From: palumbon Date: Wed, 8 Jan 2025 01:55:10 -0300 Subject: [PATCH 12/16] Testing workflows --- .github/workflows/benchmarks.yml | 55 ++++++++++---------------------- package.json | 2 +- test/benchmarks.ts | 2 +- 3 files changed, 19 insertions(+), 40 deletions(-) diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml index d35dc964..62a9fde0 100644 --- a/.github/workflows/benchmarks.yml +++ b/.github/workflows/benchmarks.yml @@ -1,51 +1,30 @@ name: Run Benchmarks -on: - issue_comment: - types: - - created +on: [pull_request] jobs: run-benchmarks: - if: ${{ contains(github.event.comment.body, '[Run benchmarks]') && github.event.issue.pull_request }} + if: ${{ contains(github.event.pull_request.body, '[Run benchmarks]') }} runs-on: ubuntu-latest steps: - # - name: Checkout repository - # uses: actions/checkout@v3 - - # - name: Read .nvmrc - # run: echo "##[set-output name=NVMRC;]$(cat .nvmrc)" - # id: nvm - # - name: Use Node.js (.nvmrc) - # uses: actions/setup-node@v3 - # with: - # node-version: "${{ steps.nvm.outputs.NVMRC }}" - - # - name: Install dependencies - # run: npm install + - name: Checkout repository + uses: actions/checkout@v3 + - name: Read .nvmrc + run: echo "##[set-output name=NVMRC;]$(cat .nvmrc)" + id: nvm + - name: Use Node.js (.nvmrc) + uses: actions/setup-node@v3 + with: + node-version: "${{ steps.nvm.outputs.NVMRC }}" + - name: Install dependencies + run: npm install - # - name: Run benchmarks - # id: benchmarks - # run: npm run test:benchmarks + - name: Run benchmarks + run: npm run test:benchmarks | tail -n +7 > bench-results.txt + continue-on-error: true - name: Post results to comment uses: peter-evans/commit-comment@v3 with: - repository: ${{ github.repository }} - comment-id: ${{ github.event.comment.id }} - body: | - ## Benchmark Results - ``` - ┌─────────┬───────────────┬─────────────────┬─────────────────────┬────────────┐ - │ (index) │ message │ fqn │ time │ iterations │ - ├─────────┼───────────────┼─────────────────┼─────────────────────┼────────────┤ - │ 0 │ 'flushEvents' │ 'empty' │ 1.0739654541015624 │ 30 │ - │ 1 │ 'flushEvents' │ 'visuals_1' │ 0.48952223459879557 │ 30 │ - │ 2 │ 'flushEvents' │ 'visuals_100' │ 0.2899084726969401 │ 30 │ - │ 3 │ 'flushEvents' │ 'ticks_1' │ 0.8966011683146159 │ 30 │ - │ 4 │ 'flushEvents' │ 'ticks_100' │ 49.76229190826416 │ 30 │ - │ 5 │ 'flushEvents' │ 'onCollide_1' │ 1.091204325358073 │ 30 │ - │ 6 │ 'flushEvents' │ 'onCollide_100' │ 48.2887056350708 │ 30 │ - └─────────┴───────────────┴─────────────────┴─────────────────────┴────────────┘ - ``` + body-path: 'bench-results.txt' diff --git a/package.json b/package.json index 617c5ceb..3862610f 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "test:wtest": "mocha --delay -t 10000 -r ts-node/register/transpile-only test/wtest.ts", "test:printer": "mocha --parallel -r ts-node/register/transpile-only test/printer.test.ts", "test:parser": "mocha -r ts-node/register/transpile-only test/parser.test.ts", - "test:benchmarks": "mocha -t 50000 -r ts-node/register/transpile-only test/benchmarks.ts", + "test:benchmarks": "mocha -t 100000 -r ts-node/register/transpile-only test/benchmarks.ts", "lint:fix": "eslint . --fix", "validate:wollokVersion": "ts-node scripts/validateWollokVersion.ts", "prepublishOnly": "npm run validate:wollokVersion && npm run build && npm test", diff --git a/test/benchmarks.ts b/test/benchmarks.ts index adc64d6f..e58efa88 100644 --- a/test/benchmarks.ts +++ b/test/benchmarks.ts @@ -8,7 +8,7 @@ import { buildEnvironment } from './assertions' should() -describe('Wollok Game', () => { +describe('Benchmarks', () => { const results: any[] = [] after(() => console.table(results)) From b324001072c94a5c544ce1e943b0d7e7e78d2994 Mon Sep 17 00:00:00 2001 From: palumbon Date: Wed, 8 Jan 2025 03:32:33 -0300 Subject: [PATCH 13/16] Longer benchmarks --- package.json | 2 +- test/benchmarks.ts | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 3862610f..b742fd42 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "test:wtest": "mocha --delay -t 10000 -r ts-node/register/transpile-only test/wtest.ts", "test:printer": "mocha --parallel -r ts-node/register/transpile-only test/printer.test.ts", "test:parser": "mocha -r ts-node/register/transpile-only test/parser.test.ts", - "test:benchmarks": "mocha -t 100000 -r ts-node/register/transpile-only test/benchmarks.ts", + "test:benchmarks": "mocha -t 999999 -r ts-node/register/transpile-only test/benchmarks.ts", "lint:fix": "eslint . --fix", "validate:wollokVersion": "ts-node scripts/validateWollokVersion.ts", "prepublishOnly": "npm run validate:wollokVersion && npm run build && npm test", diff --git a/test/benchmarks.ts b/test/benchmarks.ts index e58efa88..d2fa4f7f 100644 --- a/test/benchmarks.ts +++ b/test/benchmarks.ts @@ -29,7 +29,7 @@ describe('Benchmarks', () => { const time = totalTime / iterations - const deltaError = Math.max(0.1, expectedTime * 0.1) // 0.1 or 10 % + const deltaError = expectedTime * 0.15 // 15 % restore() // console.info(`${message} - ${fqn} - ${time} ms (${iterations} iterations)`) @@ -38,13 +38,13 @@ describe('Benchmarks', () => { }) } - benchmark('empty', 0.55) - benchmark('visuals_1', 0.4) - benchmark('visuals_100', 0.3) - benchmark('ticks_1', 0.8) - benchmark('ticks_100', 44) - benchmark('onCollide_1', 0.8) - benchmark('onCollide_100', 44) + benchmark('empty', 3.5) + benchmark('visuals_1', 3.1) + benchmark('visuals_100', 2.6) + benchmark('ticks_1', 7.7) + benchmark('ticks_100', 430) + benchmark('onCollide_1', 7.5) + benchmark('onCollide_100', 440) }) }) @@ -58,7 +58,8 @@ async function measure(programFQN: string, message: string): Promise { interpreter.send(message, game, interpreter.reify(0)) // Fill caches const startTime = performance.now() - interpreter.send(message, game, interpreter.reify(1)) + for (let ms = 1; ms < 10; ms++) + interpreter.send(message, game, interpreter.reify(ms)) const endTime = performance.now() const elapsedTime = endTime - startTime From cfb9fc9fae0a5d317b0f82318e09066e0c7a490c Mon Sep 17 00:00:00 2001 From: palumbon Date: Wed, 8 Jan 2025 12:15:35 -0300 Subject: [PATCH 14/16] Update expected results on benchmarks based on CI --- test/benchmarks.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/benchmarks.ts b/test/benchmarks.ts index d2fa4f7f..8cf48a67 100644 --- a/test/benchmarks.ts +++ b/test/benchmarks.ts @@ -38,13 +38,13 @@ describe('Benchmarks', () => { }) } - benchmark('empty', 3.5) - benchmark('visuals_1', 3.1) - benchmark('visuals_100', 2.6) - benchmark('ticks_1', 7.7) - benchmark('ticks_100', 430) - benchmark('onCollide_1', 7.5) - benchmark('onCollide_100', 440) + benchmark('empty', 6) + benchmark('visuals_1', 4) + benchmark('visuals_100', 4) + benchmark('ticks_1', 11) + benchmark('ticks_100', 637) + benchmark('onCollide_1', 11) + benchmark('onCollide_100', 675) }) }) From d1ee6f627d3b3446aaac854c8c6a2a096373e58b Mon Sep 17 00:00:00 2001 From: palumbon Date: Wed, 8 Jan 2025 12:32:39 -0300 Subject: [PATCH 15/16] Small refactors --- src/interpreter/runtimeModel.ts | 2 +- src/model.ts | 5 +++-- src/wre/game.ts | 8 ++++---- test/benchmarks.ts | 4 ++-- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/interpreter/runtimeModel.ts b/src/interpreter/runtimeModel.ts index b370f381..f6bdec28 100644 --- a/src/interpreter/runtimeModel.ts +++ b/src/interpreter/runtimeModel.ts @@ -320,7 +320,7 @@ export class Evaluation { if (node.is(Method)) if (node.isNative()) evaluation.natives.set(node, get(natives, `${node.parent.fullyQualifiedName}.${node.name}`)!) - else if (node.fromProperty()) { + else if (node.fromProperty) { evaluation.natives.set(node, compilePropertyMethod(node)) node.compiled = true } diff --git a/src/model.ts b/src/model.ts index 77fe92b3..808b6dd6 100644 --- a/src/model.ts +++ b/src/model.ts @@ -677,10 +677,11 @@ export class Method extends Node { isConcrete(): this is { body: Body } { return !this.isAbstract() && !this.isNative() } isNative(): this is { body?: Body } { return this.body === KEYWORDS.NATIVE } - fromProperty(): boolean { return this.isSynthetic && !!this.parent.lookupField(this.name) } - get hasNativeImplementation(): boolean { return this.isNative() || this.compiled } + @cached + get fromProperty(): boolean { return this.isSynthetic && this.parameters.length < 2 && !!this.parent.lookupField(this.name) } + @cached get hasVarArgs(): boolean { return !!last(this.parameters)?.isVarArg } diff --git a/src/wre/game.ts b/src/wre/game.ts index 47877459..55a0633a 100644 --- a/src/wre/game.ts +++ b/src/wre/game.ts @@ -1,5 +1,5 @@ import { GAME_MODULE } from '../constants' -import { assertIsNotNull, assertIsNumber, Execution, NativeFunction, Natives, RuntimeObject, RuntimeValue } from '../interpreter/runtimeModel' +import { assertIsNotNull, assertIsNumber, Evaluation, Execution, NativeFunction, Natives, RuntimeObject, RuntimeValue } from '../interpreter/runtimeModel' const { round } = Math @@ -15,7 +15,7 @@ const getPosition = getter('position') const getX = getter('x') const getY = getter('y') -const getObjectsIn: NativeFunction = function* (position: RuntimeObject, ...visuals: RuntimeObject[]): Execution { +const getObjectsIn = function* (this: Evaluation, position: RuntimeObject, ...visuals: RuntimeObject[]): Execution { const result: RuntimeObject[] = [] const x = (yield* getX.call(this, position))?.innerNumber @@ -67,7 +67,7 @@ const game: Natives = { *getObjectsIn(self: RuntimeObject, position: RuntimeObject): Execution { const visuals = self.get('visuals')! - return (yield* getObjectsIn.call(this, position, ...visuals.innerCollection!))! + return yield* getObjectsIn.call(this, position, ...visuals.innerCollection!) }, *say(self: RuntimeObject, visual: RuntimeObject, message: RuntimeObject): Execution { @@ -86,7 +86,7 @@ const game: Natives = { const otherVisuals = visuals.innerCollection!.filter(obj => obj != visual) const position = (yield* getPosition.call(this, visual))! - return (yield* getObjectsIn.call(this, position, ...otherVisuals))! + return yield* getObjectsIn.call(this, position, ...otherVisuals) }, *title(self: RuntimeObject, title?: RuntimeObject): Execution { diff --git a/test/benchmarks.ts b/test/benchmarks.ts index 8cf48a67..8f078bd2 100644 --- a/test/benchmarks.ts +++ b/test/benchmarks.ts @@ -39,7 +39,7 @@ describe('Benchmarks', () => { } benchmark('empty', 6) - benchmark('visuals_1', 4) + benchmark('visuals_1', 4.5) benchmark('visuals_100', 4) benchmark('ticks_1', 11) benchmark('ticks_100', 637) @@ -58,7 +58,7 @@ async function measure(programFQN: string, message: string): Promise { interpreter.send(message, game, interpreter.reify(0)) // Fill caches const startTime = performance.now() - for (let ms = 1; ms < 10; ms++) + for (let ms = 1; ms < 10; ms++) interpreter.send(message, game, interpreter.reify(ms)) const endTime = performance.now() From dbe14b0c6e598f6f020b858bb321377fa5028cfb Mon Sep 17 00:00:00 2001 From: palumbon Date: Wed, 8 Jan 2025 13:02:17 -0300 Subject: [PATCH 16/16] More benchmarks --- test/benchmarks.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/benchmarks.ts b/test/benchmarks.ts index 8f078bd2..ee5c4035 100644 --- a/test/benchmarks.ts +++ b/test/benchmarks.ts @@ -41,10 +41,11 @@ describe('Benchmarks', () => { benchmark('empty', 6) benchmark('visuals_1', 4.5) benchmark('visuals_100', 4) - benchmark('ticks_1', 11) + benchmark('ticks_1', 12) benchmark('ticks_100', 637) benchmark('onCollide_1', 11) - benchmark('onCollide_100', 675) + benchmark('onCollide_10_same_position', 5000) + benchmark('onCollide_100_diff_positions', 675) }) })