ashconnell / physx-js

PhysX for JavaScript
101 stars 11 forks source link

Are there any metrics about performance of this library? #14

Closed kujukuju closed 3 years ago

kujukuju commented 3 years ago

It sounds ideal to get to use physx in the web, especially for applications that have separate web and native clients. Does this library have any performance metrics comparing it to other popular js bindings such as Ammo or Bullet? Thanks.

prestomation commented 3 years ago

I'm unaware of any write ups on performance comparisons.

This example scene is kind of old, running in Amazon Sumerian from 2019. It's running the physics engine in a webworker(off the main thread). You can switch this single, contrived sample scene in ammo/physx/cannonjs. This will provide some info.

You can see here the PhysX build is the largest built size(although it's possible emscripten has made improvements here), but in my limited testing PhysX is the most performant. Additionally, last year I was able to get mulithreading working in PhysX without too much trouble, I'm not sure this is possible with any other engine currently compiling to WASM. This may or may not be important, depending on how much work the physics engine will be doing in your application.

kujukuju commented 3 years ago

Very informative, thank you! Do you have any more information about multithreading physx-js in webasm? This sounds very promising, physics performance has historically been the main bottle neck and limitation for most of my games on mobile web.

prestomation commented 3 years ago

Here are some key points I can remember:

You can turn on pthreads with -s USE_PTHREADS=1 in Emscripten and get most of the way there. Because of how pthreads worked on top of webworkers at the time(unsure if it has changed), you have to predefine how many threads you want. This is so the runtime can start the workers before they are used. This is because of how webworkers are started. This is because new Worker('worker.js'); is putting the act of creating the worker on the event loop, but they don't start until that method is done. PhysX will 'create' a thread and then immediately block, waiting for it to start up. These ideas are incompatible., so you have to tell the runtime to prestart these threads. At the time, this number was a 'build-time' flag, but looks like this improvement was implemented: https://github.com/emscripten-core/emscripten/issues/10231 I'm assuming that more native threading support in WASM will make this concern go away.

A similar problem was that at the time Emscripten could not build a WASM module that had shared memory support(for multi threading) but would work in a single threaded fashion in browsers that did not support this. I'm unsure if this was a WASM limitation, or just because of how Emscripten always allocated memory in a fixed way. It's not too difficult to create two module builds and then at runtime decide which to load though. I'm unsure if this has changed, but this will almost certainly be fixed as WASM/emcription improve.

The other general problem is that there is some amount of overhead in every function call to WASM from javascript. In the way the engine I was using(Sumerian) was structured, without any other changes multithreading provided no improvements because of how the engine called physx methods to discover physics object positions. I had to restructure things and ended up using a single block of memory to store all physics object positions, which the javascript engine access directly by index. This was to avoid this kind of overhead. Of course this is unrelated to multithreading, and the kind of performance problem you'll see with any WASM interop with a large amount of function calls.

kujukuju commented 3 years ago

Thanks again @prestomation, looking forward to trying this out soon. Seems very promising. I'll have to think about where the lowest data transfer boundary is to cutoff wasm vs javascript as well. I appreciate the help.