Skip to content

Commit

Permalink
refactor: support optimize massive attrs clone
Browse files Browse the repository at this point in the history
  • Loading branch information
Aarebecca committed Nov 5, 2024
1 parent d09378b commit 45f6ac0
Show file tree
Hide file tree
Showing 23 changed files with 339 additions and 59 deletions.
1 change: 1 addition & 0 deletions __tests__/demos/perf/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export { circles } from './circles';
export { rects } from './rect';
export { image } from './image';
export { attrUpdate } from './attr-update';
export { massiveAttrs } from './massive-attrs';
59 changes: 59 additions & 0 deletions __tests__/demos/perf/massive-attrs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Rect, runtime } from '@antv/g';

export async function massiveAttrs(context) {
const { canvas, gui } = context;

runtime.enableMassiveParsedStyleAssignOptimization = true;

await canvas.ready;

console.time('massiveAttrs');

for (let i = 0; i < 10000; i++) {
const rect = new Rect({
style: {
x: Math.random() * 640,
y: Math.random() * 640,
width: 10 + Math.random() * 40,
height: 10 + Math.random() * 40,
fill: '#1890FF',
stroke: '#F04864',
lineWidth: 4,

// extra attrs
'attr-a': 1,
'attr-b': 2,
'attr-c': 3,
'attr-d': 4,
'attr-e': 5,
'attr-f': 6,
'attr-g': 7,
'attr-h': 8,
'attr-i': 9,
'attr-j': 10,
'attr-k': 11,
'attr-l': 12,
'attr-m': 13,
'attr-n': 14,
'attr-o': 15,
'attr-p': 16,
'attr-q': 17,
'attr-r': 18,
'attr-s': 19,
'attr-t': 20,
'attr-u': 21,
'attr-v': 22,
'attr-w': 23,
'attr-x': 24,
'attr-y': 25,
'attr-z': 26,
},
});

canvas.appendChild(rect);
}

canvas.addEventListener('rerender', () => {
console.timeEnd('massiveAttrs');
});
}
13 changes: 13 additions & 0 deletions packages/g-components/src/Arrow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,19 @@ export interface ArrowStyleProps extends BaseStyleProps {
export class Arrow extends CustomElement<ArrowStyleProps> {
static tag = 'arrow';

static PARSED_STYLE_LIST = new Set([
...CustomElement.PARSED_STYLE_LIST,
'body',
'startHead',
'endHead',
'startHeadOffset',
'endHeadOffset',
'stroke',
'lineWidth',
'opacity',
'strokeOpacity',
]);

private body: Line | Path | Polyline;
private startHead?: DisplayObject;
private endHead?: DisplayObject;
Expand Down
11 changes: 11 additions & 0 deletions packages/g-components/src/Sector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,17 @@ export interface SectorStyleProps extends BaseStyleProps {
}

export class Sector extends CustomElement<SectorStyleProps> {
static PARSED_STYLE_LIST = new Set([
...CustomElement.PARSED_STYLE_LIST,
'startAngle',
'endAngle',
'sr',
'sr0',
'sradius',
'sx',
'sy',
]);

static tag = 'sector';

private path: Path;
Expand Down
11 changes: 11 additions & 0 deletions packages/g-components/src/Sector2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,17 @@ function computeArcSweep(startAngle: number, endAngle: number) {
}

export class Sector extends Path {
static PARSED_STYLE_LIST = new Set([
...Path.PARSED_STYLE_LIST,
'x',
'y',
'sr',
'sr0',
'radius',
'startAngle',
'endAngle',
]);

// parsedStyle: any;
constructor(config) {
super(config);
Expand Down
22 changes: 20 additions & 2 deletions packages/g-lite/src/css/StyleValueRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { isNil, isUndefined } from '@antv/util';
import { vec3 } from 'gl-matrix';
import type { DisplayObject } from '../display-objects';
import { EMPTY_PARSED_PATH } from '../display-objects/constants';
import type { GlobalRuntime } from '../global-runtime';
import { runtime, type GlobalRuntime } from '../global-runtime';
import { GeometryAABBUpdater } from '../services';
import { AABB } from '../shapes';
import type { BaseStyleProps, Tuple3Number } from '../types';
Expand Down Expand Up @@ -660,7 +660,8 @@ export class DefaultStyleValueRegistry implements StyleValueRegistry {
const oldClipPath = object.parsedStyle.clipPath;
const oldOffsetPath = object.parsedStyle.offsetPath;

Object.assign(object.parsedStyle, attributes);
assignParsedStyle(object, attributes);
// Object.assign(object.parsedStyle, attributes);

let needUpdateGeometry = !!options.forceUpdateGeometry;
if (!needUpdateGeometry) {
Expand Down Expand Up @@ -1000,3 +1001,20 @@ export class DefaultStyleValueRegistry implements StyleValueRegistry {
}
}
}

function assignParsedStyle(
object: DisplayObject,
attributes: Record<string, any>,
) {
if (!runtime.enableMassiveParsedStyleAssignOptimization) {
Object.assign(object.parsedStyle, attributes);
return;
}

const list = (object.constructor as typeof DisplayObject).PARSED_STYLE_LIST;
for (const key in attributes) {
if (list.has(key)) {
object.parsedStyle[key] = attributes[key];
}
}
}
10 changes: 10 additions & 0 deletions packages/g-lite/src/display-objects/Circle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ export class Circle extends DisplayObject<
CircleStyleProps,
ParsedCircleStyleProps
> {
static PARSED_STYLE_LIST: Set<string> = new Set([
...DisplayObject.PARSED_STYLE_LIST,
'cx',
'cy',
'cz',
'r',
'isBillboard',
'isSizeAttenuation',
]);

constructor(options: DisplayObjectConfig<CircleStyleProps> = {}) {
super({
type: Shape.CIRCLE,
Expand Down
54 changes: 0 additions & 54 deletions packages/g-lite/src/display-objects/CustomElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ export interface BaseCustomElementStyleProps extends BaseStyleProps {}
export abstract class CustomElement<
CustomElementStyleProps,
> extends DisplayObject<CustomElementStyleProps & BaseCustomElementStyleProps> {
// static get observedAttributes(): string[] {
// return [];
// }

isCustomElement = true;

// private shadowNodes: DisplayObject[] = [];
Expand Down Expand Up @@ -46,54 +42,4 @@ export abstract class CustomElement<
oldParsedValue?: any,
newParsedValue?: any,
): void;

// private handleMounted = (e: FederatedEvent) => {
// if (e.target === this) {
// // this.shadowNodes.forEach((node) => {
// // // every child and its children should turn into a shadow node
// // // a shadow node doesn't mean to be unrenderable, it's just unsearchable in scenegraph
// // node.shadow = true;
// // });

// if (this.connectedCallback) {
// this.connectedCallback();
// }
// }
// };

// private handleUnmounted = (e: FederatedEvent) => {
// if (e.target === this) {

// }
// };

// private handleChildInserted = (e: FederatedEvent) => {
// (e.target as DisplayObject).forEach((node) => {
// // append children like other shapes after mounted
// if (!this.isConnected) {
// this.shadowNodes.push(node as DisplayObject);
// }
// });
// };

// private handleChildRemoved = (e: FederatedEvent) => {
// (e.target as DisplayObject).forEach((node) => {
// node.shadow = false;
// });
// };

// private handleAttributeChanged = <Key extends keyof CustomElementStyleProps>(
// e: MutationEvent,
// ) => {
// // only listen itself
// // RangeError: Maximum call stack size exceeded
// if (e.target !== this) {
// return;
// }

// const { attrName, prevValue, newValue } = e;
// if (this.attributeChangedCallback) {
// this.attributeChangedCallback(attrName as Key, prevValue, newValue);
// }
// };
}
45 changes: 45 additions & 0 deletions packages/g-lite/src/display-objects/DisplayObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,51 @@ export class DisplayObject<
StyleProps extends BaseStyleProps = any,
ParsedStyleProps extends ParsedBaseStyleProps = any,
> extends Element<StyleProps, ParsedStyleProps> {
static PARSED_STYLE_LIST = new Set([
'class',
'className',
'clipPath',
'cursor',
'display',
'draggable',
'droppable',
'fill',
'fillOpacity',
'fillRule',
'filter',
'increasedLineWidthForHitTesting',
'lineCap',
'lineDash',
'lineDashOffset',
'lineJoin',
'lineWidth',
'miterLimit',
'hitArea',
'offsetDistance',
'offsetPath',
'offsetX',
'offsetY',
'opacity',
'pointerEvents',
'shadowColor',
'shadowType',
'shadowBlur',
'shadowOffsetX',
'shadowOffsetY',
'stroke',
'strokeOpacity',
'strokeWidth',
'strokeLinecap',
'strokeLineJoin',
'strokeDasharray',
'strokeDashoffset',
'transform',
'transformOrigin',
'textTransform',
'visibility',
'zIndex',
]);

/**
* contains style props in constructor's params, eg. fill, stroke...
*/
Expand Down
11 changes: 11 additions & 0 deletions packages/g-lite/src/display-objects/Ellipse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@ export class Ellipse extends DisplayObject<
EllipseStyleProps,
ParsedEllipseStyleProps
> {
static PARSED_STYLE_LIST: Set<string> = new Set([
...DisplayObject.PARSED_STYLE_LIST,
'cx',
'cy',
'cz',
'rx',
'ry',
'isBillboard',
'isSizeAttenuation',
]);

constructor(options: DisplayObjectConfig<EllipseStyleProps> = {}) {
super({
type: Shape.ELLIPSE,
Expand Down
6 changes: 6 additions & 0 deletions packages/g-lite/src/display-objects/Group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ export interface ParsedGroupStyleProps extends ParsedBaseStyleProps {
</g>
*/
export class Group extends DisplayObject {
static PARSED_STYLE_LIST: Set<string> = new Set([
...DisplayObject.PARSED_STYLE_LIST,
'width',
'height',
]);

constructor(options: DisplayObjectConfig<GroupStyleProps> = {}) {
super({
type: Shape.GROUP,
Expand Down
10 changes: 10 additions & 0 deletions packages/g-lite/src/display-objects/HTML.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ export interface ParsedHTMLStyleProps extends ParsedBaseStyleProps {
* @see https://github.com/pmndrs/drei#html
*/
export class HTML extends DisplayObject<HTMLStyleProps, ParsedHTMLStyleProps> {
static PARSED_STYLE_LIST: Set<string> = new Set([
...DisplayObject.PARSED_STYLE_LIST,
'x',
'y',
'$el',
'innerHTML',
'width',
'height',
]);

constructor({ style, ...rest }: DisplayObjectConfig<HTMLStyleProps> = {}) {
super({
type: Shape.HTML,
Expand Down
14 changes: 14 additions & 0 deletions packages/g-lite/src/display-objects/Image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,20 @@ export class Image extends DisplayObject<
ImageStyleProps,
ParsedImageStyleProps
> {
static PARSED_STYLE_LIST: Set<string> = new Set([
...DisplayObject.PARSED_STYLE_LIST,
'x',
'y',
'z',
'src',
'width',
'height',
'isBillboard',
'billboardRotation',
'isSizeAttenuation',
'keepAspectRatio',
]);

constructor(options: DisplayObjectConfig<ImageStyleProps> = {}) {
super({
type: Shape.IMAGE,
Expand Down
16 changes: 16 additions & 0 deletions packages/g-lite/src/display-objects/Line.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,22 @@ export interface ParsedLineStyleProps extends ParsedBaseStyleProps {
* Also support for using marker.
*/
export class Line extends DisplayObject<LineStyleProps, ParsedLineStyleProps> {
static PARSED_STYLE_LIST: Set<string> = new Set([
...DisplayObject.PARSED_STYLE_LIST,
'x1',
'y1',
'x2',
'y2',
'z1',
'z2',
'isBillboard',
'isSizeAttenuation',
'markerStart',
'markerEnd',
'markerStartOffset',
'markerEndOffset',
]);

private markerStartAngle = 0;
private markerEndAngle = 0;

Expand Down
Loading

0 comments on commit 45f6ac0

Please sign in to comment.