Skip to content

Commit

Permalink
Merge branch 'master' into constructor-performace
Browse files Browse the repository at this point in the history
  • Loading branch information
asturur committed May 27, 2024
2 parents 11c9db9 + 9e48de1 commit 190053f
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 41 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## [next]

- perf(): Rework constructors to avoid the extra perf cost of current setup [#9891](https://github.com/fabricjs/fabric.js/pull/9891)
- perf(ObjectGeometry): replace cache key string with array [#9887](https://github.com/fabricjs/fabric.js/pull/9887)
- docs(): Improve JSDOCs for BlendImage [#9876](https://github.com/fabricjs/fabric.js/pull/9876)
- fix(Group): Pass down the abort signal from group to objects [#9890](https://github.com/fabricjs/fabric.js/pull/9890)
- fix(util): restore old composeMatrix code for performances improvement [#9851](https://github.com/fabricjs/fabric.js/pull/9851)
Expand Down
97 changes: 97 additions & 0 deletions src/benchmarks/transformMatrixKey.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { FabricObject, Group } from '../../dist/index.mjs';

// Swapping of calcCornerCoords in #9377

// OLD CODE FOR REFERENCE AND IMPLEMENTATION TEST

class OldObject extends FabricObject {
transformMatrixKey(skipGroup = false) {
const sep = '_';
let prefix = '';
if (!skipGroup && this.group) {
prefix = this.group.transformMatrixKey(skipGroup) + sep;
}
return (
prefix +
this.top +
sep +
this.left +
sep +
this.scaleX +
sep +
this.scaleY +
sep +
this.skewX +
sep +
this.skewY +
sep +
this.angle +
sep +
this.originX +
sep +
this.originY +
sep +
this.width +
sep +
this.height +
sep +
this.strokeWidth +
this.flipX +
this.flipY
);
}
}

class OldGroup extends Group {
transformMatrixKey(skipGroup = false) {
return OldObject.prototype.transformMatrixKey.call(this, skipGroup);
}
}

// END OF OLD CODE

const newComplexObject = new FabricObject({ width: 100, height: 100 });
const newComplexGroup = new Group([newComplexObject]);
new Group([newComplexGroup]);

const oldComplexObject = new OldObject({ width: 100, height: 100 });
const oldComplexGroup = new OldGroup([oldComplexObject]);
new OldGroup([oldComplexGroup]);

const benchmark = (callback) => {
const start = Date.now();
callback();
return Date.now() - start;
};

const complexNew = benchmark(() => {
for (let i = 0; i < 1_000_000; i++) {
newComplexObject.transformMatrixKey();
}
});

const complexOld = benchmark(() => {
for (let i = 0; i < 1_000_000; i++) {
oldComplexObject.transformMatrixKey();
}
});

console.log({ complexOld, complexNew });

const newSimpleObject = new FabricObject({ width: 100, height: 100 });

const oldSimpleObject = new OldObject({ width: 100, height: 100 });

const simpleNew = benchmark(() => {
for (let i = 0; i < 1_000_000; i++) {
newSimpleObject.transformMatrixKey();
}
});

const simpleOld = benchmark(() => {
for (let i = 0; i < 1_000_000; i++) {
oldSimpleObject.transformMatrixKey();
}
});

console.log({ simpleOld, simpleNew });
56 changes: 23 additions & 33 deletions src/shapes/Object/ObjectGeometry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ import type { StaticCanvas } from '../../canvas/StaticCanvas';
import { ObjectOrigin } from './ObjectOrigin';
import type { ObjectEvents } from '../../EventTypeDefs';
import type { ControlProps } from './types/ControlProps';
import { resolveOrigin } from '../../util/misc/resolveOrigin';

type TMatrixCache = {
key: string;
key: number[];
value: TMat2D;
};

Expand Down Expand Up @@ -437,40 +438,29 @@ export class ObjectGeometry<EventSpec extends ObjectEvents = ObjectEvents>
this.aCoords = this.calcACoords();
}

transformMatrixKey(skipGroup = false): string {
const sep = '_';
let prefix = '';
transformMatrixKey(skipGroup = false): number[] {
let prefix: number[] = [];
if (!skipGroup && this.group) {
prefix = this.group.transformMatrixKey(skipGroup) + sep;
prefix = this.group.transformMatrixKey(skipGroup);
}
return (
prefix +
this.top +
sep +
this.left +
sep +
this.scaleX +
sep +
this.scaleY +
sep +
this.skewX +
sep +
this.skewY +
sep +
this.angle +
sep +
this.originX +
sep +
this.originY +
sep +
this.width +
sep +
this.height +
sep +
this.strokeWidth +
this.flipX +
this.flipY
prefix.push(
this.top,
this.left,
this.width,
this.height,
this.scaleX,
this.scaleY,
this.angle,
this.strokeWidth,
this.skewX,
this.skewY,
+this.flipX,
+this.flipY,
resolveOrigin(this.originX),
resolveOrigin(this.originY)
);

return prefix;
}

/**
Expand All @@ -487,7 +477,7 @@ export class ObjectGeometry<EventSpec extends ObjectEvents = ObjectEvents>
}
const key = this.transformMatrixKey(skipGroup),
cache = this.matrixCache;
if (cache && cache.key === key) {
if (cache && cache.key.every((x, i) => x === key[i])) {
return cache.value;
}
if (this.group) {
Expand Down
16 changes: 8 additions & 8 deletions test/unit/object_geometry.js
Original file line number Diff line number Diff line change
Expand Up @@ -343,11 +343,11 @@
var key3 = cObj.transformMatrixKey();
cObj.width = 5;
var key4 = cObj.transformMatrixKey();
assert.notEqual(key1, key2, 'keys are different');
assert.equal(key1, key3, 'keys are equal');
assert.notEqual(key4, key2, 'keys are different');
assert.notEqual(key4, key1, 'keys are different');
assert.notEqual(key4, key3, 'keys are different');
assert.notDeepEqual(key1, key2, 'keys are different');
assert.deepEqual(key1, key3, 'keys are equal');
assert.notDeepEqual(key4, key2, 'keys are different');
assert.notDeepEqual(key4, key1, 'keys are different');
assert.notDeepEqual(key4, key3, 'keys are different');
});

QUnit.test('transformMatrixKey depends from originX/originY', function(assert) {
Expand All @@ -358,9 +358,9 @@
var key2 = cObj.transformMatrixKey();
cObj.originY = 'center';
var key3 = cObj.transformMatrixKey();
assert.notEqual(key1, key2, 'keys are different origins 1');
assert.notEqual(key1, key3, 'keys are different origins 2');
assert.notEqual(key2, key3, 'keys are different origins 3');
assert.notDeepEqual(key1, key2, 'keys are different origins 1');
assert.notDeepEqual(key1, key3, 'keys are different origins 2');
assert.notDeepEqual(key2, key3, 'keys are different origins 3');
});

QUnit.test('isOnScreen with object that include canvas', function(assert) {
Expand Down

0 comments on commit 190053f

Please sign in to comment.