Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[g] 提升首屏性能 #1117

Closed
xiaoiver opened this issue Aug 10, 2022 · 9 comments
Closed

[g] 提升首屏性能 #1117

xiaoiver opened this issue Aug 10, 2022 · 9 comments
Assignees

Comments

@xiaoiver
Copy link
Contributor

xiaoiver commented Aug 10, 2022

目前在每一帧结束后,都会针对发生改变的节点重新构建 R 树,在这一过程中会重新计算脏节点的包围盒,是开销较大的环节:

renderingService.hooks.endFrame.tap(PrepareRendererPlugin.tag, () => {
  this.syncRTree();
});

g-canvas 的渲染在脏矩形同样在 endFrame 这一 hook 中完成,且由于是顺序执行,因此需要等待上面构建 R 树完成后:

renderingService.hooks.endFrame.tap(CanvasRendererPlugin.tag, () => {
  if (this.clearFullScreen) {
    // 全屏擦除
    renderByZIndex(this.renderingContext.root);
  } else {
    // 脏矩形渲染
  }
});

但对于首屏来说并不需要等待这一过程,构建 R 树的目的也是为了后续脏矩形最小粒度更新以及快速拾取判定。
因此可以将该过程改成异步非阻塞,至少对于首次渲染应当如此。

@xiaoiver xiaoiver self-assigned this Aug 10, 2022
@xiaoiver
Copy link
Contributor Author

xiaoiver commented Aug 10, 2022

另一个影响首屏的点是排序,并不是每次添加子节点,都需要重新对父节点排序:

sortable.sorted = displayObject.childNodes.slice().sort(sortByZIndex);

例如新添加的子节点并没有设置 z-index 时不需要触发父节点的重排,可以直接使用子节点列表。

在 5w 节点的场景下可以节省 1s 的排序时间:

截屏2022-08-10 上午11 45 59

实际渲染时间如下:

截屏2022-08-10 上午11 40 55

@xiaoiver
Copy link
Contributor Author

xiaoiver commented Aug 10, 2022

最后就是可以减少状态切换。可以看出大量的开销出在对于原生方法例如 context.stroke() context.fill() 的调用上:

截屏2022-08-10 下午12 53 34

这一点 ECharts 也在文章中提及:
https://www.infoq.cn/article/ByHjSpUD0KrhKSulyYED

xiaoiver added a commit that referenced this issue Aug 10, 2022
@xiaoiver
Copy link
Contributor Author

@antv/util 中构建后存在的 __spreadArray 也会影响,因此可以避免 ... 的使用:

截屏2022-08-10 下午2 01 24

@xiaoiver
Copy link
Contributor Author

xiaoiver commented Aug 11, 2022

对比 4.0 在渲染时间上耗时几乎一致:

截屏2022-08-11 下午3 14 06

更大的开销反倒是在创建 Path 的部分。

xiaoiver added a commit that referenced this issue Aug 12, 2022
* feat: init annotation plugin

* feat: create selectable ui

* fix: change to the latest renderer plugin usage

* feat: add drawers

* feat: add draw & hover style

* feat: support selectable rect

* fix: move inheritable properties to parent group element #1108

* fix: use radial gradient cache in g-svg

* feat: support marker-start/end in g-webgl

* feat: support marker for polygon in g-webgl

* fix: remove annotation

* fix: resolve merge conflict

* feat: support marker offset for path #1077

* chore: add test case for marker

* chore: add integration testcase for marker

* refactor: split selectable plugin from annotation

* chore: add testcase for clippath

* Publish

 - @antv/g-canvas@1.7.0
 - @antv/g-canvaskit@0.6.0
 - @antv/g-components@1.7.0
 - @antv/g-devtool@0.10.0
 - @antv/g-gesture@0.0.19
 - @antv/g-image-exporter@0.5.0
 - @antv/g-layout-blocklike@1.7.0
 - @antv/g-math@1.7.0
 - @antv/g-mobile-canvas-element@0.6.0
 - @antv/g-mobile-canvas@0.7.0
 - @antv/g-mobile-svg@0.7.0
 - @antv/g-mobile-webgl@0.7.0
 - @antv/g-plugin-3d@1.7.0
 - @antv/g-plugin-a11y@0.4.0
 - @antv/g-plugin-annotation@0.1.0
 - @antv/g-plugin-box2d@1.7.0
 - @antv/g-plugin-canvas-path-generator@1.1.0
 - @antv/g-plugin-canvas-picker@1.7.0
 - @antv/g-plugin-canvas-renderer@1.7.0
 - @antv/g-plugin-canvaskit-renderer@1.1.0
 - @antv/g-plugin-control@1.7.0
 - @antv/g-plugin-css-select@1.7.0
 - @antv/g-plugin-device-renderer@1.7.0
 - @antv/g-plugin-dom-interaction@1.7.0
 - @antv/g-plugin-dragndrop@1.6.0
 - @antv/g-plugin-gpgpu@1.7.0
 - @antv/g-plugin-html-renderer@1.7.0
 - @antv/g-plugin-image-loader@1.1.0
 - @antv/g-plugin-matterjs@1.7.0
 - @antv/g-plugin-mobile-interaction@0.7.0
 - @antv/g-plugin-physx@1.7.0
 - @antv/g-plugin-rough-canvas-renderer@1.7.0
 - @antv/g-plugin-rough-svg-renderer@1.7.0
 - @antv/g-plugin-svg-picker@1.7.0
 - @antv/g-plugin-svg-renderer@1.7.0
 - @antv/g-plugin-webgl-device@1.7.0
 - @antv/g-plugin-webgpu-device@1.7.0
 - @antv/g-plugin-yoga@1.7.0
 - @antv/g-shader-components@1.7.0
 - @antv/g-svg@1.7.0
 - @antv/g-web-components@1.7.0
 - @antv/g-webgl@1.7.0
 - @antv/g-webgpu@1.7.0
 - @antv/g@5.7.0
 - @antv/react-g@1.7.0
 - @antv/g-site@1.7.0

* fix: custom element should trigger attribute changed callback after connected

* fix: make clippath valid on ancestor #1109

* fix: picking should account for clippath on ancestor #1109

* fix: event on/off

* Publish

 - @antv/g-canvas@1.7.1
 - @antv/g-canvaskit@0.6.1
 - @antv/g-gesture@0.0.20
 - @antv/g-mobile-canvas@0.7.1
 - @antv/g-plugin-annotation@0.1.1
 - @antv/g-plugin-canvas-picker@1.7.1
 - @antv/g-plugin-canvas-renderer@1.7.1
 - @antv/g@5.7.1
 - @antv/react-g@1.7.1

* fix: support relative length unit for dx/dy #1111

* Publish

 - @antv/g-canvas@1.7.2
 - @antv/g-canvaskit@0.6.2
 - @antv/g-gesture@0.0.21
 - @antv/g-mobile-canvas@0.7.2
 - @antv/g-mobile-webgl@0.7.1
 - @antv/g-plugin-annotation@0.1.2
 - @antv/g-plugin-canvas-renderer@1.7.2
 - @antv/g-plugin-canvaskit-renderer@1.1.1
 - @antv/g-plugin-device-renderer@1.7.1
 - @antv/g-plugin-image-loader@1.1.1
 - @antv/g-webgl@1.7.1
 - @antv/g-webgpu@1.7.1
 - @antv/g@5.7.2
 - @antv/react-g@1.7.2

* fix: use native isPointInPath method first #1112

* fix: emit draw:move event

* fix: disable drawing with right mouse

* fix: downgrade Path / Polyline to Line for better perf in g-webgl #1113

* fix: apply filter to Image & Text correctly #1114

* chore: add testcase for filter

* Publish

 - @antv/g-canvas@1.7.3
 - @antv/g-canvaskit@0.6.3
 - @antv/g-gesture@0.0.22
 - @antv/g-mobile-canvas@0.7.3
 - @antv/g-mobile-svg@0.7.1
 - @antv/g-mobile-webgl@0.7.2
 - @antv/g-plugin-annotation@0.1.3
 - @antv/g-plugin-canvas-picker@1.7.2
 - @antv/g-plugin-canvas-renderer@1.7.3
 - @antv/g-plugin-device-renderer@1.7.2
 - @antv/g-plugin-svg-renderer@1.7.1
 - @antv/g-svg@1.7.1
 - @antv/g-webgl@1.7.2
 - @antv/g-webgpu@1.7.2
 - @antv/g@5.7.3
 - @antv/react-g@1.7.3
 - @antv/g-site@1.7.1

* fix: use viewport point to render drawer

* feat: interactive event such as PointerEvent and WheelEvent can be cloned #1115

* fix: draw rect with rotation

* fix: copy event point

* fix: account for camera rotation when clearing dirty rectangle #1116

* fix: reduce re-ordering on fcp #1117

* chore: update annotation docs

Co-authored-by: yuqi.pyq <yuqi.pyq@antgroup.com>
Co-authored-by: yuanzi <liaopei.lp@antgroup.com>
@xiaoiver
Copy link
Contributor Author

xiaoiver commented Oct 21, 2022

另外应当尽量减少对于 gl-matrix 的使用,特别是每个对象都有的属性例如 AABB、Transform。
很多渲染引擎都会自己实现 Vec3 或者 Mat4,这样可以避免大量 vec3.create() 的调用,减少底层 Float32Array 的使用。

@xiaoiver
Copy link
Contributor Author

xiaoiver commented Oct 24, 2022

#1120

多余的事件传递可以精简,例如 MOUNTED 没必要冒泡,直接在根节点上触发即可。

@xiaoiver
Copy link
Contributor Author

截屏2023-01-30 下午2 09 51

大量 GC 发生在 memoized 方法中,这是由于解析属性时转换创建 CSSUnitValue 带来的,对于 Number 类型的值没有必要创建额外的带单位的 CSSValue 类。

@xiaoiver
Copy link
Contributor Author

xiaoiver commented Jun 12, 2023

画布初始化阶段使用异步方法,原本是考虑到:

  • WebGPU 初始化 API 本身就是异步的
  • 部分渲染插件初始化是异步的,例如 g-plugin-yoga 加载 WASM,g-plugin-canvaskit-renderer 加载系统字体

但这会导致 g-canvasg-svg 这样没使用异步特性的插件集受到影响:

  • 编译出的代码包含 asyncToGenerator,导致运行时 run microtask 非常耗时(见下图)
  • 过深的调用栈带来大量 GC 耗时(见下图)
截屏2023-06-12 上午10 18 31

换成同步方法后,同样初始化画布耗时大幅减少(10k Circles 140 -> 80ms),microtask 这一项直接没了:

截屏2023-06-12 上午10 37 36

需要异步初始化方法:

  • g-webgpu 现在需要在异步加载完成后内部再触发一次渲染,过程中 mounted 的图形加入一个 pending 列表,加载完成后触发它们的 mounted 事件

@xiaoiver
Copy link
Contributor Author

截屏2023-06-12 下午3 03 12

xiaoiver added a commit that referenced this issue Jun 12, 2023
* fix: change canvas' init hook frin async to sync #1117

* Publish

 - @antv/g-canvas@1.9.47
 - @antv/g-canvaskit@0.8.44
 - @antv/g-gesture@0.0.82
 - @antv/g-lite@1.0.69
 - @antv/g-mobile-canvas@0.8.55
 - @antv/g-mobile-svg@0.8.59
 - @antv/g-mobile-webgl@0.7.73
 - @antv/g-plugin-3d@1.7.56
 - @antv/g-plugin-a11y@0.4.51
 - @antv/g-plugin-annotation@0.2.68
 - @antv/g-plugin-box2d@1.7.52
 - @antv/g-plugin-canvas-renderer@1.7.59
 - @antv/g-plugin-canvaskit-renderer@1.1.53
 - @antv/g-plugin-control@1.7.53
 - @antv/g-plugin-device-renderer@1.7.69
 - @antv/g-plugin-dom-interaction@1.7.51
 - @antv/g-plugin-dragndrop@1.6.50
 - @antv/g-plugin-html-renderer@1.7.55
 - @antv/g-plugin-image-loader@1.1.53
 - @antv/g-plugin-matterjs@1.7.52
 - @antv/g-plugin-mobile-interaction@0.7.50
 - @antv/g-plugin-physx@1.7.53
 - @antv/g-plugin-rough-canvas-renderer@1.7.53
 - @antv/g-plugin-rough-svg-renderer@1.7.55
 - @antv/g-plugin-svg-renderer@1.8.59
 - @antv/g-plugin-webgl-device@1.7.53
 - @antv/g-plugin-yoga@1.7.50
 - @antv/g-plugin-zdog-canvas-renderer@1.0.18
 - @antv/g-plugin-zdog-svg-renderer@1.0.17
 - @antv/g-shader-components@1.7.54
 - @antv/g-svg@1.8.59
 - @antv/g-webgl@1.7.73
 - @antv/g-webgpu@1.7.72
 - @antv/g@5.16.32
 - @antv/react-g@1.8.78
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant