Web worker 仍然使主线程卡顿。

huangapple go评论74阅读模式
英文:

Web worker still janks main thread

问题

I’m having a strange issue with a fairly complex ThreeJS scene. I’ve spent a few days moving the entire 3D scene to an offscreencanvas and I’ve moved the loading of my GLB files and texture maps to a web worker. This all works and I’m able to render the scene and it all looks the same as it did before, when I had a traditional canvas element.

不过,我在页面上有一个加载中的旋转图标,当所有资源加载完毕并渲染场景后,这个旋转图标开始出现卡顿。我尝试了一种方法,将所有的3D对象都设置为不可见,然后在渲染循环的每次迭代中逐个显示它们,直到它们全部可见。我可以清楚地看到,在场景渲染一些带有反射效果的玻璃对象时,我的加载图标开始变得卡顿。我之前在传统画布上也看到过类似的行为,所以我猜测这对渲染器来说是一项繁重的任务。

但是为什么我在主线程上看到了这种卡顿呢?我已经查看了Chrome的内存标签,但我必须承认,我不太清楚那里显示的内容。不幸的是,由于这个项目具有商业敏感性,仍处于研发阶段,我无法分享演示,但是否有人能够解释一下发生了什么,或者告诉我如何在Chrome的开发工具中查看独立的内存线程?也许我的Web Worker 已经超负荷了吗?

非常感谢任何指导。

编辑:

@Kaiido 加载GLB和图像文件现在更快,对主线程没有影响,所以使用Web Worker 并非毫无意义。

这是Chrome性能标签的屏幕截图,但说实话,我不太清楚我在看什么!:

Web worker 仍然使主线程卡顿。

而且当我输入 about:gpu 时,看到的是这样的:

Web worker 仍然使主线程卡顿。

所以我猜这真的只是对显卡的要求太高了?毕竟,我在办公环境中有一个相当复杂的3D角色,带有骨骼动画和面部变形,但我已经花了数周时间减小我的纹理图的大小,切换到ThreeJS中最简单的3D材质类型,并大幅度优化了我的动画帧。我不知道我还能做什么!而且我也是逐个显示单个3D对象,以便渲染器可以在初始化每个对象之间稍作休息。

难道真的没有办法使用我的GPU上可用的独立内存线程吗? :o(

Web worker 仍然使主线程卡顿。

英文:

I’m having a strange issue with a fairly complex ThreeJS scene. I’ve spent a few days moving the entire 3D scene to an offscreencanvas and I’ve moved the loading of my GLB files and texture maps to a web worker. This all works and I’m able to render the scene and it all looks the same as it did before, when I had a traditional canvas element.

However, I have a loading spinner on my page and after all the assets have loaded and I render the scene, the spinner starts janking. I’ve tried adopting a method where all my 3D objects are invisible and I reveal them one at a time, on each iteration of the render loop until they are all visible, and I can clearly see my spinner is becoming janky when the scene renders some glass objects with reflections on. I saw this same behaviour before, with the traditional canvas so I guess this is an intensive undertaking for the renderer.

But why am I seeing this jank on the main thread!? I’ve had a look through Chrome’s Memory tab but I must confess I don’t really know what I’m looking at in there. I can’t share a demo, unfortunately because the project is commercially sensitive and still in R&D, but can anyone shed any light at all on what on earth is happening please? Or perhaps point to me how I might be able to see separate memory threads in Chrome’s dev tools? Perhaps my web worker has simply max’d out its thread?

Thanks so much for any pointers

EDIT:

@Kaiido Loading the GLB and image files is now faster and has no effect on the main thread, so using the web worker isn't entirely for nothing.

Here is a screen grab of Chrome's Performance tab, but to be honest I don't really know what I'm looking at! :

Web worker 仍然使主线程卡顿。

and here's what I see when I type about:gpu:

Web worker 仍然使主线程卡顿。

So I guess it really is just the demands I'm putting on the Graphics Card? At the end of the day, I have a fairly complex 3D character with skeleton animations and facial morphs in an office environment, but I've already spent weeks reducing the sizes of my texture maps, changing to the simplest 3D material types in ThreeJS and massively optimising my animation frames. I don't know what more I can do! And I'm also revealing as single 3D object at a time so that the renderer can take a breath in between initialising each one.

Is there really no way to use the separate memory threads available on my GPU? :o(

Web worker 仍然使主线程卡顿。

答案1

得分: 2

Web-Worker + OffscreenCanvas 的设置将允许将所有 CPU 工作移动到并发线程上。

但是 GPU 工作仍然在单一的 GPU 进程中完成。因此,如果你的 GPU 进程被其中一个线程锁定,另一个线程也会被锁定,即使 CPU 线程实际上是空闲的。

你可以检查你的开发工具的 性能 选项卡,精确定位你的应用程序中的瓶颈所在,以及是否确实是在 GPU 线程中出现了锁定。

一个可能的解决方法是强制使你的旋转器使用软件加速而不是 GPU 加速。不清楚当前的实现方式,所以很难确定你需要做什么改变,但你可以开始使用 canvas.getContext("2d", { willReadFrequently: true }) 来创建一个降级的 2D 画布,并且可能可以使用该 2D 上下文来实现你的旋转器。

英文:

The Web-Worker + OffscreenCanvas setup will allow to move all the CPU work on a concurrent thread.

But the GPU work is still done on a single GPU process. So if your GPU process is locked by one of the threads, the other one will also be locked, even if the CPU thread is actually free.

You can check your dev-tools's Performance tab to check exactly where's the bottleneck in your app, and if indeed it's in the GPU thread that it locks.
One long-shot workaround could be to force your spinner to use software acceleration instead of GPU acceleration. Not seeing how it's done currently it's hard to tell what you should change, but you can start a deaccelerated 2D canvas doing canvas.getContext("2d", { willReadFrequently: true }) and you can probably use that 2D context do implement your spinner.

huangapple
  • 本文由 发表于 2023年5月29日 18:42:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76356648.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定